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