[英]How about a base class with a non-virtual destructor?
如果我在子类中声明了“新的运算符”,是否可以将没有虚拟析构函数的类用作基类?
以下代码会导致运行时问题吗:
class B {
public:
~B() { }
};
class D: public B {
private:
void* operator new(size_t);
}
您可以将具有非虚拟析构函数的类用作基类,而不管如何在派生类中重写operator new
。
您必须确保避免的一件事是,如果要销毁的实例属于任何派生类型,则使用带有指向基础的指针的delete
,因为这会导致未定义的行为 。 在派生类中重写operator new
不会改变这一事实。
您仍然可以说Base * p = ::new Derived;
从而造成危险情况。
这是一组简单的准则,适用于何时应将析构函数虚拟化
http://www.parashift.com/c++-faq/virtual-dtors.html
如果打算防止构造派生类的对象,则将构造函数设为私有,而不是new
运算符。
C ++语言并不需要一个基类有virtual
析构函数。 因此,您问题的直接答案是“是”,您可以拥有一个没有虚拟析构函数的基类。
但是,您不能实例化派生对象,并且无法通过基类指针进行delete
而无需调用未定义行为。
class Base
{
};
class Derived
:
public Base
{
public:
std::string mString;
};
Base* p = new Derived;
delete p;
您正在delete
Base
指针,但是*p
的动态类型是Derived
并且Base
没有virtual
析构函数,因此将调用UB:
在第一个替代方案(删除对象)中,如果操作数的静态类型不同于其动态类型,则静态类型应为操作数动态类型的基类,并且静态类型应具有虚拟析构函数或行为未定义。 在第二种选择(删除数组)中,如果要删除的对象的动态类型不同于其静态类型,则行为是不确定的(73)。
您也不能采用这种欺骗手段:
Base* p = new Derived;
Derived* d = dynamic_cast <Derived*> (p);
delete d;
...因为仅当目标是多态的(即,至少具有1个virtual
成员)时,才能使用dynamic_cast
树,而Base
没有。
因此,即使您问题的直接答案是“是”, 真正的答案是“不要那样做”。
虚拟dtor不是基类的要求,您当然可以对所有定义的结果进行操作。 无需使用op new或任何东西。
与准则有关的问题案例是在指向指向派生实例的基础的指针上使用delete时。
如果您的设计确保删除绝不会那样做,则可以继续进行。 尽管适当地记录下来是一个好主意,以便将来的开发人员不要急于“解决”这种情况或不违反规则。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.