1

如果我有类似的东西

class Base1 {};

class Base2 {};

class Derived : public Base1, public Base2 {};

然后构造 Derived 对象的构造函数调用顺序是

Base1
Base2 

即按照它们出现的顺序

class Derived : public Base1, public Base2 {};

但是,如果我将其更改为派生类: public Base1, virtual public Base2 {}; 然后构造函数调用的顺序变为

Base2
Base1

我不明白为什么会这样?

另一个简单的疑问:虚拟继承Base1的意义和目的是什么。

4

3 回答 3

4

这些只是规则。正在构造的最派生类首先初始化层次结构中的所有虚拟基类,然后再开始初始化其非虚拟直接基类。

规则来自标准 (ISO/IEC 14882:2011) 第 12.6.2 [class.base.init] / 10 节。

这种方法的基本原理是,它确保所有基类在其派生类之前初始化,无论它们是否是虚拟基类。

于 2012-04-24T12:54:20.793 回答
3

关于初始化的顺序,Charles已经答对了:就是规则,先声明顺序的虚基,然后声明顺序的非虚基,然后声明顺序的成员变量。

虚拟继承是什么意思?这意味着您的对象派生自该特定基础,但是如果在层次结构中多个子对象(完整类型的基础)实际上继承自同一基础类型,则将仅存在一个基础子对象。您可以在那里阅读virtual关键字,因为我愿意base与完整类型的其他对象分享我的关键字。

struct ubase {};
struct sbase {};
struct A : ubase, virtual sbase {};   // has a sbase subobject, but is willing to share..
struct B : ubase, virtual sbase {};   // ... but want to have my own ubase
struct C : A, B {};                   // only one sbase subobject, shared by A and B
                                      // ... but two ubase subobjects, A::ubase and B::ubase

根据第二个问题,你想什么时候使用虚拟继承?每当在类型层次结构中,您最终可能不止一次地从同一个基类继承,而在您的设计中,所有这些基类的出现都只是一个。一般来说,除了少数特殊情况外,使用虚拟继承是很不常见的。

于 2012-04-24T13:07:40.727 回答
1

至于虚拟继承。当你有一个像下面这样的派生类时,它就会发挥作用

class A {};
class B : public virtual A {} ;
class C : public virtual A {} ;
class D : B, C { }  // this class has only one instance of A!

又名钻石问题!

于 2012-04-24T12:59:50.193 回答