0

如果我在子类中声明“operator new”私有,我可以使用没有虚拟析构函数的类作为基类吗?

以下代码是否会导致运行时问题:

class B {
public:
    ~B() { }
};

class D: public B {
private:
    void* operator new(size_t);
}
4

5 回答 5

4

operator new无论您在派生类中如何覆盖,都可以将具有非虚拟析构函数的类用作基类。

delete如果要销毁的实例是任何派生类型,则必须确保避免使用指向基的指针,因为这会导致未定义的行为。在派生类中重写operator new并不会改变这一事实。

于 2013-05-31T14:40:44.287 回答
3

您仍然可以说Base * p = ::new Derived;并因此造成危险情况。

于 2013-05-31T14:34:54.120 回答
2

下面是一组简单的指导方针,说明何时应该将析构函数设为虚拟

http://www.parashift.com/c++-faq/virtual-dtors.html

如果您打算阻止构造派生类的对象,则将构造函数设为私有,而不是new运算符。

于 2013-05-31T14:34:34.900 回答
2

C++ 语言不要求基类具有virtual析构函数。因此,您的问题的直接答案是“是的”,您可以拥有一个没有虚拟析构函数的基类。

但是,您不能实例化派生对象,delete而是通过基类指针而不调用未定义行为。

class Base
{
};

class Derived
:
  public Base
{
  public:
    std::string mString;
};

Base* p = new Derived;
delete p;

您正在delete输入一个Base指针,但是动态类型*pDerived并且Base没有virtual析构函数,因此这会调用 UB:

5.3.5/3 删除

在第一种选择(删除对象)中,如果操作数的静态类型与其动态类型不同,则静态类型应为操作数动态类型的基类,并且静态类型应具有虚拟析构函数或行为未定义. 在第二种选择(删除数组)中,如果要删除的对象的动态类型与其静态类型不同,则行为未定义。73)

你也不能像这样使用诡计:

Base* p = new Derived;
Derived* d = dynamic_cast <Derived*> (p);
delete d;

...因为如果目标是多态的,您只能将树投下dynamic_cast- 意思是,至少有 1virtual个成员 - 而Base不是。

所以,即使你的问题的直接答案是“是”,真正的答案是“不要那样做”。

于 2013-05-31T14:48:35.730 回答
0

虚拟 dtor 不是基类的要求,您当然可以使用所有定义的结果来实现。并且不需要使用 op new 或任何东西。

与该指南相关的问题案例是当 delete 用于指向 base 的指针时,该指针指向派生的实例。

如果您的设计确保删除永远不会以这种方式发生,您可以继续。尽管正确记录这一点是个好主意,这样未来的开发人员就不会急于“修复”这种情况,或者不违反规则。

于 2013-05-31T14:48:16.773 回答