如何在编译器中实现C++虚拟继承?

MKo*_*MKo 23 c++ compiler-construction inheritance virtual-inheritance

编译器如何实现虚拟继承?

在以下代码中:

class A {
  public:
    A(int) {}
};

class B : public virtual A {
  public:
    B() : A(1) {}
};

class C : public B {
  public:
    C() : A(3), B() {}
};
Run Code Online (Sandbox Code Playgroud)

编译器是否生成两个B::ctor函数实例,一个没有A(1)调用,一个带有它?因此,当B::constructor从派生类的构造函数调用时,将使用第一个实例,否则使用第二个实例.

era*_*ran 8

编译器不会创建另一个B的构造函数 - 但它忽略了A(1).由于A实际上是继承的,因此首先使用其默认构造函数构造它.并且由于它在B()调用时已经构造,因此A(1)忽略该部分.

编辑-我错过了A(3)部分C的构造初始化列表.使用虚拟继承时,只有最派生的类初始化虚拟基类.因此A将使用A(3)而不是其默认构造函数构造.其余的仍然存在 - A中间类(此处B)的任何初始化都将被忽略.

编辑2,试图回答有关上述实施的实际问题:

在Visual Studio中(至少2010年),使用标志而不是具有两个实现B().由于在调用构造函数之前B实际上继承了该标志,因此检查了该标志.如果未设置标志,则跳过调用.然后,在每个派生的类中,标志在初始化之后被重置.同样的机制是用来防止从初始化,如果它的某些部分(如果从继承, 将初始化).AAA()BACADDCDA


Ale*_*x B 8

它依赖于实现.例如,GCC(请参阅此问题)将发出两个构造函数,一个调用A(1),另一个调用.

B1()
B2() // no A
Run Code Online (Sandbox Code Playgroud)

构造B时,调用"完整"版本:

B1():
    A(1)
    B() body
Run Code Online (Sandbox Code Playgroud)

构造C时,将调用基本版本:

C():
    A(3)
    B2()
       B() body
    C() body
Run Code Online (Sandbox Code Playgroud)

事实上,即使没有虚拟继承,也会发出两个构造函数,它们将是相同的.