为什么基类的析构函数应该是虚函数?

13

在C++中,为什么基类的析构函数应该是虚函数?

5个回答

37
更好的问题是“何时和为什么”。你的问题表明你认为所有基类都应该有虚析构函数,这并不完全正确。
这将使得无法应用空基类优化,并且可能会在常见平台上将类的大小增加到原来的16倍,而不加virtual。
当您使用类型为 BaseClass* 的指针删除动态类型为 DerivedClass 的对象时,需要一个虚拟析构函数。虚拟函数使编译器将信息与对象关联起来,使其能够执行派生类的析构函数。在这种情况下缺少虚拟函数将导致未定义的行为。
如果您不需要这个,而且您的类仅被用作基类,最好将析构函数声明为 protected,从而防止用户意外地以所描述的方式删除它们。

4
另外一个优秀的描述,请参见Virtuality,具体来说,“指导原则#4:基类析构函数应该是公有且虚拟的,或者是受保护且非虚拟的。” - Robᵩ

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所指出的那样,如果您没有利用多态性,就不必这样做。然而,我试图养成声明所有析构函数为虚拟的习惯。它可以保护我免受应该声明为虚拟但忘记这样做的情况。正如Johannes所指出的那样,当虚拟标记不需要时,这种习惯可能会带来一些空间和性能上的惩罚。


4

除非您正在使用多态,否则它们不必是虚拟的。如果您使用多态,则需要将它们设置为虚拟的,以便保证继承类的析构函数被调用,从而使继承类可以进行清理。


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().

1

应该将其声明为虚函数,以确保在运行时调用继承类的析构函数而不是基类的析构函数。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接