虚拟基类的创建顺序
Posted
技术标签:
【中文标题】虚拟基类的创建顺序【英文标题】:Virtual base classes order of creation 【发布时间】:2017-07-08 06:41:32 【问题描述】:我有以下问题:
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 是困扰我的问题。
【问题讨论】:
您能否改进您的代码格式以便于阅读? 虚拟类不被“调用”。你不能“叫一个班级”。相反,对象被初始化。 你是对的,我犯了一个错误。谢谢你的解释。 【参考方案1】:第一个A1
是由B
的(非虚拟)基AA1
的(虚拟)基的初始化产生的。
首先初始化B
的所有虚基,依次为A1
、A2
和AA2
。 (AA2
的初始化导致输出A1 AA2
。)然后是直接基,其中只有一个,AA1
(其初始化打印A2 AA1
),最后是类本身,打印@987654332 @。首先是所有虚拟基地,然后是其余的非虚拟基地。
【讨论】:
非常感谢。这真的对我有很大帮助。我很难理解这个虚函数。他们是我唯一无法理解的,这个答案对我帮助很大。 第一个A1
实际上来自AA1
的虚拟基础,而不是来自AA2
的非虚拟基础(实际上是第二个A1
)。您可以通过向构造函数添加一个参数来显示它们的“调用”位置。
@DropFuriosPolaris:我原来的解释是错误的;请查看更新后的结果,感谢 Holt 的更正。【参考方案2】:
B
具有三个虚拟基类:A1
、A2
和AA2
,并根据它们出现的顺序依次初始化它们。
你看到的第一个A1
和A2
是初始化虚基A1
和A2
,但是最后一个虚基AA2
有一个非虚基A1
,所以在构造之前AA2
,你需要构造另一个A1
,这就是为什么你在AA2
之前有另一个A1
。
您可以通过运行以下 sn-p 来可视化这一点:
#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
会先被初始化(同样的原因)。
【讨论】:
以上是关于虚拟基类的创建顺序的主要内容,如果未能解决你的问题,请参考以下文章