如果使用虚拟继承,最派生的类型必须做这个虚拟基类的初始化。如果不使用虚拟继承,则直接派生类型必须进行初始化。
因此,私有 ctor 不会阻止派生类型NewClass
初始化直接基类SealingClass
,并且如果它没有被虚拟继承,AnotherClass
则不必初始化。NewClass
一些例子:
template<typename Child>
class SealingClass {
public: // for now
SealingClass() {}
};
class NewClass : public SealingClass<T> {
public:
NewClass() : SealingClass<T>() {} // allowed, SealingClass<T> is a
// direct base class
};
class AnotherClass : public NewClass {
public:
AnotherClass() : NewClass() {} // allowed, NewClass is a
// direct base class
AnotherClass() : SealingClass<T>() {} // not allowed, SealingClass<T> is
// no direct nor a virtual base class
};
class NewClass_v : public virtual SealingClass<T> {
public:
NewClass_v() : SealingClass<T>() {} // allowed, SealingClass<T> is a
// direct base class
};
class AnotherClass_v : public NewClass_v {
public:
AnotherClass_v() : NewClass_v() {} // allowed, NewClass_virt is a
// direct base class
AnotherClass_v() : SealingClass<T>() {} // allowed, SealingClass<T> is a
// virtual base class
};
现在,如果 ctorSealingClass
是私有的,则由于访问说明符而不是朋友,AnotherClass_virt
因此不允许调用此 ctor 。private
如果你省略基类的显式初始化(无论是虚拟的还是直接的),它是默认初始化的([class.base.init]/8),也就是说,默认的ctor被隐式调用(但你仍然必须有访问ctor,因此它与显式编写对默认ctor的调用相同)。
一些报价:
[class.base.init]/1
在类的构造函数的定义中,直接和虚拟基础子对象和非静态数据成员的初始化程序可以由 ctor-initializer 指定
[class.base.init]/7
在执行不是最派生类的任何类的构造函数期间,忽略 mem-initializer-id 表示虚拟基类的 mem-initializer。
[class.base.init]/10
在非委托构造函数中,初始化按以下顺序进行:
- 首先,并且仅对于最派生类的构造函数,虚拟基类按照它们出现在基类的有向无环图的深度优先从左到右遍历的顺序进行初始化,其中“从左到右” ”是派生类base-specifier-list中基类的出现顺序。
- 然后,直接基类按照它们出现在 base-specifier-list 中的声明顺序进行初始化(无论 mem-initializers 的顺序如何)。
强调我的。