虚拟基地 类 创建顺序
Virtual base classes order of creation
我有以下问题:
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
的 (non-virtual) 基 AA1
的(虚拟)基的初始化。
先初始化B
的所有虚拟基,依次为A1
、A2
、AA2
。 (AA2
的初始化导致输出 A1 AA2
。)然后是直接基,其中只有一个 AA1
(其初始化打印 A2 AA1
),以及最后 class 本身,打印 B
。所有的虚拟基地都排在第一位,然后才是剩下的 non-virtual 个。
B
有3个虚拟基类:A1
、A2
和AA2
,并根据它们出现的先后顺序,对它们进行初始化按照这个顺序。
你看到的第一个A1
和A2
是虚拟基地A1
和A2
的初始化,但最后一个虚拟基地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
的构造函数中把A1
放在A2
之前,但是A2
会在A1
之前初始化(因为是虚基A1
不是)。
- 我在
B
的构造函数中把AA1
放在AA2
之前,但是AA2
会先初始化(同理)。
我有以下问题:
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
的 (non-virtual) 基 AA1
的(虚拟)基的初始化。
先初始化B
的所有虚拟基,依次为A1
、A2
、AA2
。 (AA2
的初始化导致输出 A1 AA2
。)然后是直接基,其中只有一个 AA1
(其初始化打印 A2 AA1
),以及最后 class 本身,打印 B
。所有的虚拟基地都排在第一位,然后才是剩下的 non-virtual 个。
B
有3个虚拟基类:A1
、A2
和AA2
,并根据它们出现的先后顺序,对它们进行初始化按照这个顺序。
你看到的第一个A1
和A2
是虚拟基地A1
和A2
的初始化,但最后一个虚拟基地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
的构造函数中把A1
放在A2
之前,但是A2
会在A1
之前初始化(因为是虚基A1
不是)。 - 我在
B
的构造函数中把AA1
放在AA2
之前,但是AA2
会先初始化(同理)。