关于C++:为什么我们需要一个具有动态内存的虚拟析构函数?

why do we need a virtual destructor with dynamic memory?

本问题已经有最佳答案,请猛点这里访问。

当我们有继承时,为什么我们需要一个带有动态变量的虚拟析构函数?在静态/动态情况下,析构函数的执行顺序是什么?最派生类的析构函数不是总是先执行吗?


当试图通过基类指针来delete派生类对象时,需要在基类中有一个virtual析构函数。

庞氏案:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Foo
{
public:
  virtual ~Foo(){};
};

class Bar : public Foo
{
public:
  ~Bar() { std::cout <<"Bye-Bye, Bar"; }
};

int main()
{
  Foo* f = new Bar;
  delete f;
}

如果没有基类中的virtual析构函数,这里就不会调用Bar的析构函数。


想象一下你有这个:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class A {
  public:
  int* x;    
}
class B : public A {
  public:
  int *y;
}


main() {
  A *var = new B;
  delete var;
}

请假定一些构造函数析构函数。在这种情况下,当您删除a时,如果您有虚拟析构函数,那么将首先调用b析构函数来释放y,然后调用a's来释放x。

如果不是虚拟的,它只会调用a的析构函数leaking y。

问题是编译器不能预先知道应该调用哪个析构函数。假设上面有一个if,它根据一些输入构造a或b,并将其赋给var。通过使其虚拟化,可以使编译器在运行时解除实际调用。在运行时,它将知道哪个是基于vtable的正确析构函数。