Search code examples
c++inheritancemultiple-inheritancediamond-problem

Diamond sub-problem: non-multiple inheritance in side branch still require class constructor


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.


Solution

  • 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.