在C ++中:为什么基类的析构函数应该是虚拟的?
答案 0 :(得分:36)
更好的问题是何时以及为何。您的问题表明您认为所有基类都应该具有虚拟析构函数,这并不完全正确。
这将使得无法应用空基类优化,并且可以将类的大小乘以在公共平台上没有virtual
的情况下的16倍。
当virtual
动态类型为delete
的对象由类型为DerivedClass
的指针时,需要BaseClass*
析构函数。 virtual
使编译器在对象中关联信息,使其能够执行派生类析构函数。在这种情况下缺少virtual
会导致未定义的行为。
如果您不需要这个,并且您的类仅用作基类,则最好使用析构函数protected
,从而以所描述的方式意外地阻止用户delete
。 / p>
答案 1 :(得分:8)
您希望它们是虚拟的,以便在销毁对象时自动调用所有子类析构函数,即使它是通过指向基类的指针销毁的。在以下代码中:
class base {
public:
virtual ~base() { }
};
class derived : public base {
public:
~derived() { } // Inherits the virtual designation
};
int main(void)
{
base *b = new derived;
delete b;
}
如果基础析构函数是虚拟的,派生的析构函数将仅 。
正如Magnus指出的那样,如果你没有利用多态性,你不必这样做。但是,我试图养成将所有析构函数声明为虚拟的习惯。它保护我免受我应该宣称它们是虚拟但忘记这样做的情况。正如约翰尼斯指出的那样,当不需要虚拟指定时,这种习惯可能会造成很小的空间和性能损失。
答案 2 :(得分:4)
对于这样的情况:
class A
{
virtual ~A();
};
class B:A
{
~B();
};
A *a = new B(); //legal, since it's a downcast
delete a; //Unless the destructor is virtual, ~A() is called here instead of ~B().
答案 3 :(得分:3)
除非您使用多态,否则它们不必是虚拟的。如果你确实使用了多态,那么它们必须是虚拟的,以便保证继承类的析构函数被调用,所以继承的类可以进行清理。
答案 4 :(得分:1)
它应该是虚拟的,以确保继承类的析构函数是在运行时实际调用的析构函数,而不是被调用的基类析构函数。