可以自动将默认析构函数生成为虚拟析构函数吗?

53 c++ destructor

可以自动将默认析构函数生成为虚拟析构函数吗?

如果我定义了一个基类但没有默认的析构函数,是否会自动生成一个默认的虚拟析构函数?

Dre*_*kes 50

在C++ 11中,您可以使用:

class MyClass
{
  // create a virtual, default destructor
  virtual ~MyClass() = default;
};
Run Code Online (Sandbox Code Playgroud)

  • 与使用带有`{}`的空构造函数相比,使用`default`有什么不同吗? (3认同)

Uri*_*Uri 46

不是.将方法设为虚拟会产生相关成本,而C++的理念是不会让您为未明确声明要使用的内容付费.如果自动生成虚拟析构函数,您可能会自动支付价格.

为什么不直接定义一个空虚拟析构函数?

  • 请注意,您也可以执行`virtual~Foo()= default;`从[C++ 11]开始(http://en.cppreference.com/w/cpp/language/member_functions#Special_member_functions)(如果有人正在阅读)这是最近的) (64认同)
  • @Spencer:调用析构函数需要在运行时通过对象的vtable解析d-tor代码的地址。对于非虚拟析构函数,在编译时就知道代码的地址。 (2认同)

Mat*_*att 9

不,所有析构函数默认都不是虚拟的.

您需要在所有基类上定义虚拟析构函数

在此之上.

引用Scott Meyers的书"Effective C++":

C++语言标准在这个主题上异常清晰.当您尝试通过基类指针删除派生类对象并且基类具有非虚拟析构函数(如EnemyTarget所做)时,结果未定义

实际上,如果您认为有人可能最终从中创建派生类,那么通常使用虚拟析构函数定义类通常是个好主意.无论如何,我倾向于让所有类都有虚拟析构函数.是的,存在与此相关的成本,但是不会使其更加虚拟的成本不会超出运行时的开销.

我建议,只有当你完全确定你想要那样而不是依赖于编译器强制执行的默认非虚拟时,才使它成为非虚拟的.你可能不同意(但总结)我最近在一些遗留代码上有一个可怕的内存泄漏,我所做的就是将std :: vector添加到已经存在了几年的其中一个类中.事实证明,其中一个基类没有定义析构函数(默认析构函数为空,非虚拟!),并且没有内存被分配,因为在此之前没有内存泄漏.经过多天的调查和浪费时间......


MSa*_*ers 9

是的,通过从具有虚析构函数的基类继承.在这种情况下,您已经为多态类(例如vtable)支付了价格.


Cra*_*rks 8

Uri和Michael是对的 - 我只是补充一点,如果你不得不触摸两个文件来声明和定义析构函数,那么在标题中定义一个最小的内联是完全可以的:

class MyClass
{
   // define basic destructor right here
   virtual ~MyClass(){}

   // but these functions can be defined in a different file
   void FuncA();
   int FuncB(int etc);
}
Run Code Online (Sandbox Code Playgroud)

  • 我一直这样做,它在MSVC中链接得很好,更不用说C++标准明确允许这样做了.我猜这是GCC的一个错误. (3认同)
  • 如果您使用的是GCC,并且没有定义FuncA和FuncB非内联,那么您只会获得"未定义的vtable参考"错误,这只是因为GCC未能发出所有必要的内容以允许正确的链接. (2认同)