为什么虚拟析构函数需要删除运算符?

时间:2019-07-08 03:16:18

标签: c++11 operator-keyword virtual-destructor

考虑以下代码:

class Base {
public:
#ifdef __VIRTUAL__
   virtual ~Base() {}
#else
   ~Base() {}
#endif
};

class Derived : public Base {
public:
    ~Derived() {}
private:
    static void operator delete(void*) = delete;
};

int main() {
    Derived d;
}

它将使用cmd成功编译

g++ -std=c++11 main.cpp

但使用cmd失败

g++ -std=c++11 -D__VIRTUAL__ main.cpp

输出显示operator delete是必需的

main.cpp: In destructor ‘virtual Derived::~Derived()’:
main.cpp:12:17: error: use of deleted function ‘static void Derived::operator delete(void*)’
     ~Derived() {}
                 ^
main.cpp:14:17: error: declared here
     static void operator delete(void*) = delete;
                 ^
main.cpp: In destructor ‘virtual Derived::~Derived()’:
main.cpp:12:17: error: use of deleted function ‘static void Derived::operator delete(void*)’
     ~Derived() {}
                 ^
main.cpp:14:17: error: declared here
     static void operator delete(void*) = delete;
                 ^

这意味着如果使用虚拟析构函数,则无法删除operator delete

为什么会这样,为什么虚拟析构函数即使在堆栈上创建也需要全局operator delete

1 个答案:

答案 0 :(得分:1)

仅在删除具有动态存储持续时间的对象期间调用operator delete函数。您的程序没有调用它。

但是,该标准要求即使存在虚拟析构函数,该函数也必须可用,即使该对象从未真正被动态使用过。

在C ++ 17标准中,这是[class.dtor] / 13:

  

在定义虚拟析构函数时(包括隐式定义),将确定非数组释放函数,就好像表达式delete this出现在析构函数类的非虚拟析构函数中一样。如果查找失败或释放函数的定义已删除,则程序格式错误。 [注意:这确保了与 delete-expression 对应的对象动态类型的释放函数。 —尾注]

为什么该标准要求这样做?我不知道,但是您将不得不找到其他方法来解决您的问题。也许该线程会有用:Any way to prevent dynamic allocation of a class?