虚拟基类的创建顺序

Virtual base classes order of creation

本文关键字:顺序 创建 基类 虚拟      更新时间:2023-10-16

我有以下问题:

struct A1 {
A1() { std::cout << "A1, "; }
};
struct A2 {
A2() { std::cout << "A2, "; }
};
struct AA1 : virtual A1,  A2 {
AA1() { std::cout << "AA1, "; }
};
struct AA2 : A1, virtual A2 {
AA2(){ std::cout << "AA2, "; }
};
struct B : AA1, virtual AA2 {
B() { std::cout << "B "; }
};
int main() {
B b;
}

运行此代码时,答案是:

A1 A2 A1 AA2

A2 AA1 B

我想了解第一个A1在哪里创建。

我知道在非虚拟类之前调用虚拟类的规则,但第一个 A1 是困扰我的问题。

第一个A1是由B的(非虚拟)基AA1的(虚拟)基的初始化产生的。

B的所有虚基首先初始化,它们依次是A1A2AA2。(AA2的初始化会导致输出A1 AA2。然后是直接基,其中只有一个,AA1(其初始化打印A2 AA1),最后是类本身,打印B。首先是所有虚拟基础,然后只有其余的非虚拟基础。

>B有三个虚拟基类:A1A2AA2,根据它们的出现顺序,它将按这个顺序初始化它们。

你看到的第一个A1A2是虚拟基A1A2的初始化,但是最后一个虚拟基AA2有一个非虚拟的基A1,所以在构造AA2之前,你需要构造另一个A1,这就是为什么在AA2之前你还有另一个A1

可以通过运行以下代码片段来可视化这一点:

#include <iostream>
struct A1 {
A1(const char *s) { std::cout << "A1(" << s << ")n"; }
};
struct A2 {
A2(const char *s) { std::cout << "A2(" << s << ")n"; }
};
struct AA1 : virtual A1,  A2 {
AA1(const char *s) : A1("AA1"), A2("AA1") { std::cout << "AA1(" << s << ")n"; }
};
struct AA2 : A1, virtual A2 {
AA2(const char *s) : A1("AA2"), A2("AA2") { std::cout << "AA2(" << s << ")n"; }
};
struct B : AA1, virtual AA2 {
B() : A1("B"), A2("B"), AA1("B"), AA2("B") { std::cout << "B()n"; }
};
int main() {
B b;
}

这将输出:

A1(B)
A2(B)
A1(AA2)
AA2(B)
A2(AA1)
AA1(B)
B()

您还可以注意到此代码会发出警告,因为:

  • 我在AA2的构造函数中A2之前放了A1,但A2将在A1之前初始化(因为它是一个虚拟基,而A1不是)。
  • 我在B的构造函数中AA2之前放了AA1,但AA2将首先初始化(同样的原因)。