调用虚基类的重载构造函数

dyp*_*dyp 11 c++ constructor virtual-inheritance

有没有(实用的)绕过普通(虚拟)构造函数调用顺序的方法?

例:

class A
{
    const int i;

public:
    A()
      : i(0)
    { cout << "calling A()" << endl; }

    A(int p)
      : i(p)
    { cout << "calling A(int)" << endl; }
};

class B
    : public virtual A
{
public:
    B(int i)
      : A(i)
    { cout << "calling B(int)" << endl; }
};

class C
    : public B
{
public:
    C(int i)
      : A(i), B(i)
    { cout << "calling C(int)" << endl; }
};

class D
    : public C
{
public:
    D(int i)
      : /*A(i), */ C(i)
    { cout << "calling D(int)" << endl; }
};


int main()
{
    D d(42);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

输出:

调用A()
调用B(int)
调用C(int)
调用D(int)

我想拥有的是:

调用A(int)
调用B(int)
调用C(int)
调用D(int)


如您所见,涉及虚拟继承,这导致D的构造函数首先调用A的构造函数,但由于没有提供参数,因此它调用A().有需要初始化的const int i,所以我遇到了问题.

我想要做的是隐藏C的继承细节,这就是为什么我正在寻找一种方法来避免在D(和每个派生的)构造函数的初始化列表中调用A(i).[编辑]在这个特定的情况下,我可以假设只有非虚拟的单继承子类C(因为D是一个).[/编辑]

[编辑]

在初始化任何非虚拟基类之前初始化虚拟基类,因此只有最派生的类才能初始化虚拟基类. - 詹姆斯麦克尼利斯

这正是重点,我希望最派生的类调用虚基类构造函数. [/编辑]

考虑以下情况(上面的代码示例中没有表示):

  A
 / \
B0  B1
 \ /
  C
  |
  D  
Run Code Online (Sandbox Code Playgroud)

我理解为什么C在实例化C时必须调用A(歧义)的ctor,但为什么D在实例化D时必须调用它?

div*_*a23 7

不幸的是,您将始终必须从派生程度最高的类调用虚拟基类构造函数.

这是因为您说的是虚拟基础在从该对象实例派生的所有类之间共享.由于构造函数只能在对象的给定实例中被调用一次,因此您必须在最派生类中显式调用构造函数,因为编译器不知道有多少类共享虚拟基础(从"The"中释放(可能很差)) C++编程语言第3版,第15.2.4.1节).这是因为编译器将从最基类的构造函数开始,并且工作到派生程度最高的类.直接从虚拟基类继承的类不会通过标准调用它们的虚基类构造函数,因此必须显式调用它.