《C++ Primer》中对于虚析构函数如此解释:
自动调用基类部分的析构函数对基类的设计有重要影响。
删除指向动态分配对象的指针时,需要运行析构函数在释放对象的内存之前清除对象。处理继承层次中的对象时,指针的静态类型可能与被删除对象的动态类型不同,可能会删除实际指向派生类对象的基类类型指针。
如果删除基类指针,则需要运行基类析构函数并清除基类的成员,如果对象实际是派生类型的,则没有定义该行为,要保证运行适当的析构函数,基类中的析构函数必须是析构的。
我写了如下程序做测试:
#include<iostream>
using namespace std;
class A{
public:
A(){cout<<"this is A()"<<endl;}
~A(){cout<<"this is ~A()"<<endl;}
};
class B:public A{
public:
B(){cout<<"this is B()"<<endl;}
~B(){cout<<"this is ~B()"<<endl;}
};
int main(){
A *pa = new A;
delete pa;
pa = NULL;
B *pb = new B;
delete pb;
pb = NULL;
pa = new B;
delete pa;
pa = NULL;
return 0;
}
首先是基类未定义为虚析构函数,用基类指针指向对象B,但是B被delete掉的时候,可以看到结果中并未调用B的析构函数:
然后我们将A中的析构函数加上virtual,使之成为虚析构函数,再看看结果:
此时我们可以看到,B的析构函数被正确调用。
虚析构函数的目的就是为了保证析构函数能够正确被调用。