我正在使用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;
}
当我将A的析构函数更改为虚函数时,问题就解决了。什么是内部工作。为什么我要将A的析构函数设为虚拟。我想知道A和B的vtable会发生什么?
答案 0 :(得分:6)
虚拟析构函数只是一个虚函数,所以它遵循相同的规则。
当你调用delete a
时,会隐式调用析构函数。如果析构函数不是虚拟的,则会调用a->~A()
,因为它被称为每个其他非虚函数。
但是,如果析构函数是虚拟的,则会按预期调用~B()
:析构函数是虚函数,因此调用的是派生类的析构函数,而不是基类。
编辑:
请注意,在派生类的析构函数完成后,将隐式调用 base 类的析构函数。这与通常的虚函数不同。
答案 1 :(得分:4)
您需要知道的关键是在上面的代码中不使用虚拟析构函数是未定义的行为,而这不是您想要的。虚拟析构函数与任何其他虚函数一样 - 当您调用delete
时,程序将决定在运行时调用哪些析构函数并解决您的问题。