views:

46

answers:

1

Strange problem occurred when I tried to "solve" usual diamond problem in a usual way - using virtual inheritance:

  A
 / \* both virtual
B   C
 \ /
  D

However my base class A doesn't have default constructor, so I was to call it manually from D. However when I try to add a class E into this diamond as C-inherited

  A
 / \* both virtual
B   C
 \ / \
  D   E

it is still needed to call constructor of A in E constructor manually, i.e. C doesn't what to create A from E even though there is neither multiple inheritance nor diamond A-C-E.

class A                     
   {public: 
      A (int _N): N(_N) {};
      void show()
        {cout<<"A"<<N;} 
    protected:
      int N;
   }; 
class B: public virtual A   
   { public: 
       B(int n): A(2*n) {};
       void show()
        { cout<<"B"<<N;} 
   }; 
class C: public virtual A   
   { public: 
       C(int n): A(3*n) {};
       void show()
        { cout<<"C"<<N;} 
   }; 
class D: public B,C 
   { public: 
       D(): B(1), C(2), A(3) {};
       void show()
        { cout<<"D"<<N;} 
   }; 

class E: public virtual C
   { public:
       E(): C(1) {};
       void show()
        { cout<<"E"<<N;} 
   }; 

int main()
  {D d;       // OK
   A *a = &d; 
   a->show(); 

   E e;        // NOT OK, no function A::A() to call in E::E()
   A *a2 = &e;
   a2->show();
   return 0;
  } 

Is it possible to solve this issue without calling constructor of A from E? I need C to do it properly :-).

Or is it possible not to try to solve diamond problem at all:

A   A
|   |  no virtual at all
B   C
 \ / \
  D   E

and still try to declare object of class D with two instances of A but telling compiler to use A of C when colling from D each time? When I try to add

using C::A

into the declaration of D it still produce error of unambiguous base A.

+2  A: 

Is it possible to solve this issue without calling constructor of A from E? I need C to do it properly :-).

The constructor for the most derived class (in this case, E) is responsible for calling the constructor for any virtual base classes.

The constructor of C cannot call the constructor of A because C is not the most derived class. Virtual base classes are initialized before any direct base classes, so E must initialize by A before it can initialize C.

James McNellis
Thanks, this is understandable, so is this exact meaning of virtual inheritance? Now I see. Probably I don't need virtual inheritance here, unfortunately it won't be comfortable (since there are a lot of derivatives from E and each should call A constructor in the same way as C and so on). Maybe there is a way to bypass diamond problem without virtual inheritance (in a using-like way)?
Nick
@Nick: It's kind of hard to say with an abstract example like this. To be honest, I generally avoid complex inheritance hierarchies in code that I write. Someone else might have a good, pragmatic solution for the general case.
James McNellis
I was thinking... well, I do not need C to be child of A that much in my particular case. E could be direct child of A (together with C) instead.@James, thanks a lot again.
Nick