【问题标题】:Default constructor getting called while using virtual inheritance [duplicate]使用虚拟继承时调用默认构造函数[重复]
【发布时间】:2013-09-25 06:40:15
【问题描述】:

在下面的代码中,当我创建 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;
}

【问题讨论】:

  • 还有另一种选择来解释为什么调用它,直接关系到它是 Bvirtual 基,C 是从该基派生的。提示:B 的构造函数不是源,所以再考虑一下。
  • A(int z): a(z) {cout

标签: c++ inheritance virtual


【解决方案1】:

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

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

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

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

然后构造B子对象。

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

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

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

【讨论】:

  • 嗨,n.m,谢谢你这么详细的回答,现在我对这些事情很清楚了
猜你喜欢
  • 2018-04-18
  • 2021-06-02
  • 2012-07-26
  • 2012-04-12
  • 1970-01-01
  • 2017-12-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多