1

在下面的代码中,当我创建 C 的对象时,A'a 默认构造函数通过 B 的构造函数被调用,为什么会发生这种情况?

#include <iostream>
using namespace std;

class A
{
public:
    int a;
    A(int z): a(z) {cout<<"a is "<<a;}
    A() { cout<<" it came here\n";}
};

class B: public virtual A
{
public:
    B(int z): A(z) {cout<<"in B and z is "<<z<<"\n"; }
};

class C:public B
{
public:
    C(int z): B(z) {cout<<" In C\n"; }
};

int main()
{
    C b(6);
    cout<<b.a;
    return 0;
}
4

1 回答 1

0

这就是标准中描述虚拟继承的方式。

[12.6.2] — 首先,并且仅对于最派生类 (1.8) 的构造函数,虚拟基类按照它们出现在基的有向无环图的深度优先从左到右遍历的顺序进行初始化类,其中“从左到右”是派生类base-specifier-list中基类的出现顺序。

特别是,在构造 时CA子对象在其他任何东西(包括B子对象)之前被初始化。由于A不在有问题的构造函数mem-initializers列表中C,因此使用默认构造函数A

[12.6.2] - 然后,直接基类按照它们出现在 base-specifier-list 中的声明顺序进行初始化(无论mem-initializers的顺序如何)。

然后B构造子对象。

[12.6.2] mem -initializer-id表示虚拟基类的mem-initializer在执行不是最派生类的任何类的构造函数期间被忽略。

: A(z)在构造 的子对象B时忽略构造函数中的。BC

在日常语言中,这意味着您必须在每个直接或间接派生类中初始化一个虚拟基类,就好像它是一个直接派生类一样。如果您忘记这样做,则将强制使用默认构造函数,从而产生潜在的破坏性后果。(这就是为什么你应该努力在任何虚拟基类中使用默认构造函数或根本没有默认构造函数)。

于 2013-09-25T07:49:29.270 回答