虚拟析构函数如何工作?

Bru*_*uce 4 c++

我正在使用gcc.我知道当我们销毁由基类指针指向的派生类对象时,虚拟析构函数如何解决问题.我想知道它们是如何工作的?

class A
{
      public:
      A(){cout<<"A constructor"<<endl;}
     ~A(){cout<<"A destructor"<<endl;}

};

class B:public A
{
      public:
      B(){cout<<"B constructor"<<endl;}
      ~B(){cout<<"B destructor"<<endl;}
};       

int main()
{
  A * a = new B();
  delete a;    
  getch();
  return 0;   
} 
Run Code Online (Sandbox Code Playgroud)

当我将A的析构函数更改为虚函数时,问题就解决了.什么是内部工作.为什么我要将A的析构函数设为虚拟.我想知道A和B的vtable会发生什么?

Vla*_*lad 6

虚拟析构函数只是一个虚函数,所以它遵循相同的规则.

当你调用时delete a,隐式调用析构函数.如果析构函数不是虚拟的,则会调用a->~A()它,因为它被称为每个其他非虚函数.

但是,如果析构函数是虚拟的,则会~B()按预期调用:析构函数是虚函数,因此调用的是派生类的析构函数,而不是基类.

编辑:
请注意,在派生类的析构函数完成后,将隐式调用类的析构函数.这与通常的虚函数不同.

  • @Jack:通常是的; 析构函数是一个例外. (3认同)
  • @Jack:C++中没有构造多态:使用构造函数,你总是根据你调用的构造函数得到一个类的实例.有了破坏,它就会变得更复杂:你可以通过指向基类的指针来破坏对象. (3认同)
  • 但虚拟函数不应该具有相同的名称吗? (2认同)
  • @Jack:对于析构函数来说这是不可能的 - 它们必须与它们所属的类具有相同的名称. (2认同)
  • 幸运的是,编译器将所有析构函数视为具有相同函数的"destroy()".所以析构函数的虚拟覆盖是有效的. (2认同)

sha*_*oth 4

您需要知道的关键是,在上面的代码中不使用虚拟析构函数是未定义的行为,这不是您想要的。虚拟析构函数就像任何其他虚拟函数一样 - 当您调用程序时delete,程序将决定在运行时正确调用哪个析构函数,从而解决您的问题。

  • @Jack当你构造你的对象时,你显式地调用了“new B()”,所以此时该对象明确是一个“B”,因此调用了“B”构造函数。但是当对象被删除时,您删除的是一个“A*”,因此它被视为一个“A”对象,因此除非它是虚拟的,否则会调用“A”析构函数。 (3认同)