jsd*_*sdw 9 c++ virtual inheritance
我有一个可以继承的模板类,以便赋予一些选择功能.但是,它希望阻止任何类继承继承它的任何东西.
以下似乎实现了这一点:
template<typename Child>
class SealingClass
{
public:
/*public methods etc*/
private:
SealingClass() {}
friend Child;
};
//simplify a bit:
#define Seal( x ) public virtual SealingClass< x >
Run Code Online (Sandbox Code Playgroud)
现在,我可以继承上面的类,如下:
class NewClass: Seal(NewClass) {};
Run Code Online (Sandbox Code Playgroud)
如果我再尝试继承NewClass
,如:
class AnotherClass: public NewClass {};
Run Code Online (Sandbox Code Playgroud)
然后创建所述类的实例:
AnotherClass a;
Run Code Online (Sandbox Code Playgroud)
关于SealingClass
私有的构造函数,我得到了所需的错误.
所以,一切都按照我的意愿行事!
但是,我注意到如果我virtual
从定义中删除关键字..
#define Seal( x ) public SealingClass< x >
Run Code Online (Sandbox Code Playgroud)
..我AnotherClass
现在的实例工作得很好.
我理解virtual
在这种情况下,关键字意味着在多重继承(例如钻石继承)的情况下只定义了基类的一个实例,其中可能存在多个实例,导致模糊的函数调用等.
但是,为什么它会影响上述功能呢?
谢谢 :)
如果使用虚拟继承,则派生程度最高的类型必须初始化此虚拟基类.如果不使用虚拟继承,则直接派生类型必须进行初始化.
因此,私有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
};
Run Code Online (Sandbox Code Playgroud)
现在,如果ctor SealingClass
是私有的,AnotherClass_virt
由于private
访问说明符而不是朋友,不允许调用此ctor .
如果省略了基类的显式初始化(无论是虚拟的还是直接的),它是默认初始化的([class.base.init]/8),也就是默认调用默认的ctor(但你仍然必须有)访问ctor,所以它与显式写入默认ctor的调用相同).
一些引言:
[class.base.init]/1
在类的构造函数的定义中,可以通过ctor-initializer指定直接和虚拟基础子对象和非静态数据成员的初始化程序.
[class.base.init]/7
在执行不是最派生类的任何类的构造函数期间,将忽略mem-initializer,其中mem-initializer-id表示虚拟基类.
[class.base.init]/10
在非委托构造函数中,初始化按以下顺序进行:
- 首先,仅对于派生类最多的构造函数,虚拟基类按照它们出现在基类的有向非循环图的深度优先从左到右遍历的顺序进行初始化,其中"从左到右" "是派生类base-specifier-list中基类出现的顺序.
- 然后,直接基类按声明顺序初始化,因为它们出现在base-specifier-list中(无论mem-initializers的顺序如何).
强调我的.
归档时间: |
|
查看次数: |
418 次 |
最近记录: |