如果我在子类中声明“operator new”私有,我可以使用没有虚拟析构函数的类作为基类吗?
以下代码是否会导致运行时问题:
class B {
public:
~B() { }
};
class D: public B {
private:
void* operator new(size_t);
}
如果我在子类中声明“operator new”私有,我可以使用没有虚拟析构函数的类作为基类吗?
以下代码是否会导致运行时问题:
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;
...因为如果目标是多态的,您只能将树投下dynamic_cast
- 意思是,至少有 1virtual
个成员 - 而Base
不是。
所以,即使你的问题的直接答案是“是”,真正的答案是“不要那样做”。
虚拟 dtor 不是基类的要求,您当然可以使用所有定义的结果来实现。并且不需要使用 op new 或任何东西。
与该指南相关的问题案例是当 delete 用于指向 base 的指针时,该指针指向派生的实例。
如果您的设计确保删除永远不会以这种方式发生,您可以继续。尽管正确记录这一点是个好主意,这样未来的开发人员就不会急于“修复”这种情况,或者不违反规则。