[Okta Webinar] Learn how to a build a cloud-first strategyRegister Now

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 569
  • Last Modified:

Inheritance problem ?

Hello, I have run into an error using code similar to this:

class Bar
{
// ...
public:
 Foo *pfoo;

 Bar(Foo *afoo,int i) :foo(afoo)
 {
  //...
 }
};

// I have a couple other classes like Bar, call them Bar1 and Bar2

class Foo
{
public:
  Bar a;
  Bar1 b;
  Bar2 c;
// ...
};

class Child:public Foo
{
// ...
public:
  Child(void):Foo(),a(this,1),b(this,2),c(this,3) {}
};

The idea is that Foo acts as abase class for a bunch of derived classes, which initialize their Bar members with different values. The Bar memebrs all have a pointer to the class that contains them, so that they can use its methods.
In the Child constructor, I get the following error:
"Foo:a" is not an unambiguous base class of "Child".
This happens with every single member of Foo I try to initialize, even with ints, longs, etc. (not just classes).
What does the error mean ? How do I fix it ? I realize that I can put all the initialization in the Foo constructor, but I don't want to do this since there will be too many parameters for me to pass.

0
Sinclair
Asked:
Sinclair
  • 9
  • 4
1 Solution
 
SinclairAuthor Commented:
Edited text of question
0
 
nietodCommented:
answer coming.
0
 
nietodCommented:
It is a little hard to tell if what I'm seeing is the real problem, or just a typo in your sample.  But the code

class Bar
   {
   // ...
   public:
    Foo *pfoo;

    Bar(Foo *afoo,int i) :foo(afoo)
    {
     //...
    }
   };

will complain that "foo is not a unambiguous base class or member of Bar.".  because it is not
"pfoo" (not "foo") however is a member.  If you change this to read

class Bar
   {
   // ...
   public:
    Foo *pfoo;

    Bar(Foo *afoo,int i) :pfoo(afoo)
    {
     //...
    }
   };

that should work.
0
What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

 
nietodCommented:
In the next case, the error is pretty clear.  Foo is a base of Child, so child can construct its Foo base, but it cannot construct the members of its Foo base,  The Foo has to construct its members.  The line that is in error is
     Child(void):Foo(),a(this,1),b(this,2),c(this,3) {}

what you need to do is provide a constructor for Foo that constructs a, b, and c.  Then the child should call this constructor to cosntruct its Foo,  sort of like.


class Foo
   {
   public:
     Bar a;
     Bar1 b;
     Bar2 c;
   Foo(int A, int B, int C) : a(this,A), b(this,B), c(this,C) {};
   // ...
   };

   class Child:public Foo
   {
   // ...
   public:
     Child(void):Foo(1,2,3) {}
   };
0
 
SinclairAuthor Commented:
Thanks, nietod, and sorry for my typo in the Bar constructor. However, your solution (place all initialization in the Foo constructor) is something I have been trying to avoid, since there will be many, many parameters that I will need to pass - and they will differ depending on the child class, which means I will have to provide a Foo constructor for every possible combination of overridden Bar constructors. Is there another way to do this ?
0
 
nietodCommented:
Don't blame me I didn't write the language!

Let me see if I understand your complaint.  Are you saying (just to be specific) there are say four ways to construct a Bar.  And a Foo needs to construct 3 bars so a Foo will need 3*4=12 constructors to handle every case?  Is that the problem you are faced with?

If so, there are ways around it...sort of.  

Let me know if that is the problem, or if not try to explain it more clearly.  An explanation of the real code wouldn't hurt.   Then I'll try to give you the best solution or a choice of a few good ones.
0
 
lbrucherCommented:
Nietod was right in its explanation of the error. At the time
you try to initialize a, b and c from Child, they have already
been init'd because they belong to Foo and Foo had been init'd
already.

One quick way to still init a, b and c from Child is to have them as pointers to Bar, Bar1 and Bar2. So, you'd not need to
init them in the constructor. Just init them to NULL in Foo's constructor and new them anywhere you want in Child.
If you don't like pointers and your Bar class support the = operator you can also init them to some default value in Foo contructor and reassign them in Child: a = Bar(this, 1); b = Bar1(); etc...

Hope this helps.
0
 
nietodCommented:
lbrucher, as you said, I was right.  so why did you answer?
0
 
SinclairAuthor Commented:
nietod, sorry, I did not mean to pick on you :-)
Yes, I am having the exact problem you described (except with larger numbers). It looks like lbrucher has a workable solution (pointers initialized using new), so I am going to give points to him unless you can present a better solution (I am sort of afraid of messing up my code with memory leaks).
0
 
nietodCommented:
I think you understood, but just in case, that was a joke.  At times like this I often wish I did write the language.

That solution will work, but may be less efficient than others, and certainly can make your code harder to write.

One technique would be to use a parameter class heirarchy.  For example, say a Bar can be initialized in three ways, with a char, with an int, or with a double.  Then you would create a class hierarchy of 3 classes (and probably a 4th abstract base class) that will specify arguments to the Bar constructor.  Well, let me give you and example,

class BarConPrm :
{
};

class BarChrConPrm : public BarConPrm
{
public:
    char Chr;
};

class BarIntConPrm : public BarConPrm
{
public:
    int Int;
};

class BarDblConPrm : public BarConPrm
{
public:
    double Dbl;
};

continues.
0
 
nietodCommented:
Then rather than having three constructors for Bar, you would have only one.  It would take a pointer or reference (constant reference is best in my opinion) to a parameter base class object.  the constructor would then typecast the parameter base class object to one of the concrete parameter class types, extract the parameters, and construct the Bar, like

Bar::Bar(const BarConPrm &Prm)
{
   const BarConPrm *PrmPtr = &Prm;
   const BarIntConPrm *Intptr = dynamic_cast<BarIntConPrm *,PrmPtr>;
   const BarChrConPrm *ChrPtr = dynamic_cast<BarChrConPrm *,PrmPtr>;
   const BarDblConPrm *DblPtr = dynamic_cast<BarDblConPrm *,PrmPtr>;

   if (IntPtr)
    ???? =  IntPtr->Int;
   else if (ChrPtr)
     ???? = ChrPtr->Chr;
   else
     ???? = DblPtr->Dbl;  
 
}
0
 
nietodCommented:
Now say the class Foo has three Bar's that need to be constructed.  Foo's constructor will take 3 classes of the constructor parameter heirarchy, like

Foo::Foo(const BarPrmCon &P1,const BarPrmCon &P2,const BarPrmCon &P3) : Bar1(P1),Bar2(P2),Bar3(P3) {};

Now you have 1 bar constructor and 1 Foo constructor instead of 3 foo constructors and 9 bar constructors.  The constructors will be slighly slower, however.  But the total efficency (compared to embedded pointers) should be better.

Questions?  There are other options, but this is probably the best, at least as far as I can tell with what you've given me.
0
 
SinclairAuthor Commented:
Thanks, nietod, I will do it that way and see if it works. I like your method because it provides even more flexibility than pointers and straight constructor overloading. I would give points to lbrucher, too, but I don't know if I can do that under the EE system...
0
 
nietodCommented:
You can't if you are really generious, you can ask a "dummy" question just for him (put his name on it so no one else answers).  That's ussually nice to do, but I'm not so sure I would feel to compelled to do so in this case.  It was really inappropriate for him to have answered.  I had answered your oringinal question completely and you had asked for additional information.  He It is customary to let the expert who answered provide the information, or at least if another expert provides it to be helpful, they do so in a comment.  But I think he is knew and will learn...

If you have additional questions as you impliment this technique let me know.  I use it myself.
0

Featured Post

Concerto's Cloud Advisory Services

Want to avoid the missteps to gaining all the benefits of the cloud? Learn more about the different assessment options from our Cloud Advisory team.

  • 9
  • 4
Tackle projects and never again get stuck behind a technical roadblock.
Join Now