Diamond子问题:side branch中的非多重继承仍然需要类构造函数

时间:2010-07-18 19:39:07

标签: c++ inheritance multiple-inheritance diamond-problem

当我试图以通常的方式“解决”通常的钻石问题时发生了奇怪的问题 - 使用虚拟继承:

  A
 / \* both virtual
B   C
 \ /
  D

但是我的基类A没有默认构造函数,所以我是从D手动调用它。但是当我尝试将C类添加到此钻石作为C继承时

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

仍然需要手动调用E构造函数中的A的构造函数,即即使既没有多重继承也没有钻石A-C-E,C不会从E创建A。

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;
  } 

是否可以在不调用E的构造函数的情况下解决此问题?我需要C才能正确地做到这一点:-)。

或者根本不可能尝试解决钻石问题:

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

仍然尝试使用两个A实例来声明D类的对象但是告诉编译器每次从D进行coling时使用A的C?当我尝试添加

using C::A

进入D的声明它仍然产生明确的基础A的错误。

2 个答案:

答案 0 :(得分:3)

  

是否可以在不调用E的构造函数的情况下解决此问题?我需要C才能正确地做到: - )。

派生程度最高的类(在本例中为E)的构造函数负责调用任何虚拟基类的构造函数。

C的构造函数无法调用A的构造函数,因为C不是派生类最多的类。虚拟基类在之前初始化任何直接基类,因此E必须在A初始化之前初始化C

答案 1 :(得分:3)

是的,虚拟基类构造函数调用与虚函数重写不同:

  • 您可以覆盖派生类中的虚函数;
  • 只有在其中一个基类中覆盖该函数而在其他基类中没有覆盖该函数时,必须才能覆盖虚函数;
  • 您不能覆盖基类构造函数的虚拟基类的init-list。

这意味着:

  • 就虚函数重写而言,虚拟继承根本不会影响单继承;
  • 但是当涉及到基类构造函数调用时,虚拟继承会影响每个派生类。