【问题标题】:Multipath inheritance with only one base virtual只有一个基本虚拟的多路径继承
【发布时间】:2021-11-08 17:33:21
【问题描述】:

据我所知,virtual 确保只有一个基类属性的副本被继承到派生类。在多重继承中,首先调用所有基类的构造函数,然后调用派生类的构造函数。在下面的代码中,为什么 B 类的构造函数连续调用了两次?据我了解,输出应该是

B
B1
B2
D

但输出结果是

B
B
B1
B2
D

这是完整的代码。

#include <iostream>

class B
{
public:
    B(){std::cout << "B" << std::endl;}
};

class B1:public B
{
public:
    B1(){std::cout << "B1" << std::endl;}
};

class B2:virtual public B
{
public:
    B2(){std::cout << "B2" << std::endl;}
};

class D:public B1, public B2
{
public:
    D(){std::cout << "D" << std::endl;}
};

int main()
{
    D d1;
}

【问题讨论】:

  • class B1:public B 不是虚拟继承。

标签: c++ inheritance multipath


【解决方案1】:

B1对B的继承也必须是虚的。

虚拟继承并不意味着“在层次结构的其余部分中查找该类的继承实例”,它意味着“仅对该层次结构中的所有虚拟继承使用一个继承实例”。

【讨论】:

  • 好吧,我现在明白 B1 和 B2 仍然有自己的 B。但是为什么构造函数的顺序是 B->B->B1->B2->D ?不应该是 B->B1->B->B2->D 吗?当 B 对 B1 和 B2 都不是虚拟的时,顺序是 B->B1->B->B2->D。让B virtual for B2 如何改变构造函数的顺序?
  • 似乎可以(B 代表 D 的虚拟课程)(B 和 B1 代表 B1)(B2 代表 B2)(D 代表 D)。在这里,虚拟首先出现,但我不知道规范是否说明了虚拟类的构造是否必须始终在任何其他父类构造之前进行 - 虽然它会在它是父类的任何类的构造之前进行!
  • 经过一番研究,根据cppreference:“所有虚拟基础子对象都在任何非虚拟基础子对象之前初始化”en.cppreference.com/w/cpp/language/derived_class
  • 谢谢!我添加了更多的继承层,发现所有的虚拟类都是先初始化的。
【解决方案2】:

这是经典的“钻石问题”(described here)。您对virtual 关键字的理解是正确的,但它仅适用于同时用于B1B2 的情况。

【讨论】:

  • 内存布局真的很方便弄清楚事情。我现在了解构造函数调用顺序的行为。
【解决方案3】:

这样写你的代码:

#include <iostream>

class B
{
public:
    B(){std::cout << "B" << std::endl;}
};

class B1:public B
{
public:
    B1(){std::cout << "B1" << std::endl;}
};

class B2:public B1
{
public:
    B2(){std::cout << "B2" << std::endl;}
};

class D:public B2
{
public:
    D(){std::cout << "D" << std::endl;}
};

int main()
{
    D d1;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-10-12
    • 1970-01-01
    • 2013-02-14
    • 1970-01-01
    • 2017-03-31
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多