创建涉及虚拟继承的类的过程
The process of creating a class that involves virtual inheritance
在许多描述虚拟基类用法的教程中(通常用于解决菱形问题),它们通常具有类似于此结构设计的代码:
class Animal
{
public:
Animal()
{
cout << "Creating Animaln";
}
};
///////////////////////////
class FourLegs : virtual public Animal
{
public:
FourLegs()
{
cout << "Creating FourLegsn";
}
};
///////////////////////////
class Mammal : virtual public Animal
{
public:
Mammal()
{
cout << "Creating Mammaln";
}
};
///////////////////////////
class Fox : public FourLegs, public Mammal
{
public:
Fox()
{
cout << "Creating Foxn";
}
};
当我创建 Fox 实例时,我得到了预期的输出,只创建了一个动物:
Creating Animal
Creating FourLegs
Creating Mammal
Creating Fox
如您所见,我虚拟继承了两个 Tier-2 类。现在,如果只有一个 Tier-2 类是虚拟继承的,而另一个是公开继承的,则可能会出现有趣的输出。例如,如果 FourLegs 是继承的,而哺乳动物是继承的虚拟公共,则输出如下:
Creating Animal
Creating Animal
Creating FourLegs
Creating Mammal
Creating Fox
这很奇怪,并提出了一个问题:在继承树中的某处创建涉及虚拟继承的类的完整过程是什么?
另一方面,如果 I FourLegs 继承了虚拟公共,而 Mammal 是继承了公共的,那么输出就像正常一样(好像没有任何东西被继承虚拟公共):
Creating Animal
Creating FourLegs
Creating Animal
Creating Mammal
Creating Fox
直接从标准 12.6.2/10 [class.base.init]:
在非委托构造函数中,初始化按以下顺序进行:
首先,并且仅对于派生最多的类 (1.8) 的构造函数,虚拟基类按照它们在基类的有向无环图的深度优先从左到右遍历上的顺序进行初始化,其中"从左到右"是基类在派生类基说明符列表中的出现顺序。
然后,直接基类按照它们出现在基说明符列表中的声明顺序进行初始化(无论 mem 初始值设定项的顺序如何)。
然后,非静态数据成员按照它们在类定义中声明的顺序进行初始化(同样,无论 mem 初始值设定项的顺序如何)。
最后,执行构造函数主体的复合语句。
[注意:声明顺序是为了确保以与初始化相反的顺序销毁基对象和成员子对象。—尾注]
第一个项目符号说明如何使用涉及虚拟继承的类完成初始化。
意外的输出并不意外。发生这种情况是因为FourLegs
派生自Animal
并且必须调用 Animal
的构造函数。需要对所有中间类进行virtual
化来防止此问题的既定约定。您的示例的潜在问题是,FourLegs
的概念被用作遗传性状,而它应该用作组合性状。也就是说,有一个字段描述哺乳动物/动物在Mammal
或Animal
内的腿数(取决于特定要求),派生类继承该字段。
- 继承函数的重载解析
- 递归函数计算序列中的平方和(并输出过程)
- 继承期间显示未知行为的子类
- 头文件-继承c++
- 为什么在保护模式下继承升级不起作用
- 通过继承类使用来自不同命名空间的运算符
- 子目录是否继承属性,例如add_definitions,include_directories和父Cmakelist.t
- 混合组合和继承的C++问题
- 继承:构造函数,初始化C++11中基类的类C数组成员
- 从类继承时,继承的类是否会通过父类重新定义继承的变量
- 是否删除在对象构造过程中创建的对象
- 公共与私人继承
- 如何创建从同一类继承的不同对象的向量
- 如何从另一个文件继承私有成员变量和公共函数
- 在模板基类中为继承类中的可选重写生成虚拟方法
- 带有继承的C++工厂
- 我应该避免多重实现继承吗
- C++继承更改成员
- 如何拒绝一个叫做的过程以写入继承的控制台窗口
- 创建涉及虚拟继承的类的过程