默认析构函数可以自动生成为虚拟析构函数吗?
如果我定义了一个基类但没有默认析构函数,是否会自动生成默认的虚拟析构函数?
不。使方法虚拟化是有成本的,而 C++ 的理念是不让您为未明确声明要使用的东西付费。如果虚拟析构函数会自动生成,那么您将自动付出代价。
为什么不直接定义一个空的虚拟析构函数?
在 C++ 11 中,您可以使用:
class MyClass
{
// create a virtual, default destructor
virtual ~MyClass() = default;
};
是的,通过从具有虚拟析构函数的基类继承。在这种情况下,您已经为多态类(例如 vtable)付出了代价。
不,所有析构函数默认不是虚拟的。
您将需要在所有基类上定义一个虚拟析构函数
在此之上。
引用 Scott Meyers 在他的《Effective C++》一书中的话:
C++ 语言标准在这个主题上异常清晰。当您尝试通过基类指针删除派生类对象并且基类具有非虚拟析构函数(如 EnemyTarget 所做的那样)时,结果未定义
在实践中,如果您认为有人最终可能会从中创建派生类,那么使用虚拟析构函数定义一个类通常是一个好主意。无论如何,我倾向于让所有类都有虚拟析构函数。是的,这是有相关成本的,但不使其更频繁地虚拟化的成本不会增加运行时开销。
我建议,仅当您绝对确定您想要它时才将其设为非虚拟,而不是依赖编译器强制执行的默认非虚拟。您可能不同意,但是(总而言之)我最近在一些遗留代码上发生了可怕的内存泄漏,我所做的只是将 std::vector 添加到已经存在多年的类之一中。事实证明,它的一个基类没有定义析构函数(默认析构函数是空的,非虚拟的!),并且在没有内存泄漏之前没有像这样分配内存。许多天的调查和后来浪费的时间......
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);
}
目前,Uri是对的。另一方面,在你的类中声明了一个虚方法之后,无论如何你都要为虚表的存在付出代价。事实上,如果你的类有虚方法但没有虚析构函数,编译器会警告你。这可能成为自动生成默认虚拟析构函数的候选者,而不是讨厌的警告。
不,您需要将其声明为虚拟的。
有人说它永远不会默认为虚拟。这并不完全正确。
即使析构函数不是继承的,如果基类声明它的析构函数是虚拟的,派生的析构函数总是会覆盖它。
这意味着如果基类具有虚拟析构函数,您不必将派生类的析构函数定义为虚拟的,也不必显式编写:
/// All of these are unnecessary and won't change the destruction behavior
/// as long as Class inherits from a base class with a virtual destructor
virtual ~Class() = default;
// or
~Class() override = default;
// or
~Class() {}