rin*_*ng0 56 c++ inheritance controls
最近我的一位朋友问我如何在C++中阻止类继承.他希望编译失败.
我在考虑它并找到了3个答案.不确定哪个是最好的.
1)私人建设者
class CBase
{
public:
static CBase* CreateInstance()
{
CBase* b1 = new CBase();
return b1;
}
private:
CBase() { }
CBase(CBase3) { }
CBase& operator=(CBase&) { }
};
Run Code Online (Sandbox Code Playgroud)
2)使用CSealed基类,私有ctor和虚拟继承
class CSealed
{
private:
CSealed() {
}
friend class CBase;
};
class CBase : virtual CSealed
{
public:
CBase() {
}
};
Run Code Online (Sandbox Code Playgroud)
3)使用CSealed基类,受保护的ctor和虚拟继承
class CSealed
{
protected:
CSealed() {
}
};
class CBase : virtual CSealed
{
public:
CBase() {
}
};
Run Code Online (Sandbox Code Playgroud)
以上所有方法都确保不能继承CBase类.我的问题是:
1)哪种方法最好?还有其他方法吗?
2)除非CSealed类是虚拟继承的,否则方法2和3将不起作用.这是为什么 ?它与vdisp ptr有什么关系吗?
PS:
上述程序是在MS C++编译器(Visual Studio)中编译的.参考:http://www.codeguru.com/forum/archive/index.php/t-321146.html
Pet*_*wis 72
从C++ 11开始,您可以将final关键字添加到您的类中,例如
class CBase final
{
...
Run Code Online (Sandbox Code Playgroud)
我可以看到想要这样做的主要原因(以及我来寻找这个问题的原因)是将一个类标记为非子类,这样你就可以安全地使用非虚析构函数并完全避免使用vtable.
小智 11
您无法阻止继承(在C++ 11的final
关键字之前) - 您只能阻止继承类的实例化.换句话说,没有办法阻止:
class A { ... };
class B : public A { ... };
Run Code Online (Sandbox Code Playgroud)
您可以做的最好的事情是防止B类对象被实例化.在这种情况下,我建议你接受kts的建议,并记录A(或其他)不打算用于继承,给它一个非虚拟析构函数,没有其他虚函数,并留下它的事实.
Kit*_*YMG 10
您正在进行扭曲以防止进一步的子类化.为什么?记录该类不可扩展并使dtor非虚拟的事实.根据c的精神,如果有人真的想忽略你打算使用它的方式,为什么要阻止它们呢?(我从未final
在java中看到类/方法的重点).
//Note: this class is not designed to be extended. (Hence the non-virtual dtor)
struct DontExtened
{
DontExtened();
/*NOT VIRTUAL*/
~DontExtened();
...
};
Run Code Online (Sandbox Code Playgroud)
1)是品味问题.如果我看到它正确,你的更好看的第二和第三解决方案在某些情况下将错误从链接时间移动到编译时间,这通常应该更好.
2)需要虚拟继承来强制责任将(虚拟)基类初始化为基类ctor不再可达的最派生类.