虚析构,就是为了析构完全(在delete 父类指针的时候,将子类对象析构完全)
当一个类中有虚函数的时候,请将其析构函数一并virtual
看例子:
class Animal
{
public:
Animal();
~Animal(); //析构 若改成virtual ~Animal();则为虚析构
virtual void voice()=0; //纯虚函数
};
Animal::Animal()
{
cout<<"Animal()"<<endl;
}
Animal::~Animal()
{
cout<<"~Animal()"<<endl;
}
class Dog:public Animal
{
public:
Dog();
~Dog();
virtual void voice();
};
Dog::Dog()
{
cout<<"Dog()"<<endl;
}
Dog::~Dog()
{
cout<<"~Dog()"<<endl;
}
void Dog::voice()
{
cout<<"wang wang wang"<<endl;
}
int main()
{
Animal * ani=new Dog;
ani->voice();
delete ani;
return 0;
}
运行结果:
Animal()
Dog()
wang wang wang
~Animal()
结果可以看出,Dog()没有析构
但是如果把 ~Animal(); 变成 virtual ~Animal();
则输出结果为:
Animal()
Dog()
wang wang wang
~Dog()
~Animal()
结论:含有虚函数的类,析构函数也应该声明为虚函数。在delete父类指针的时候,会调用子类的析构函数,实现完整析构。
虚函数总结:
1)只有类的成员函数才能声明为虚函数
虚函数仅适用于有继承关系的类对象,所以普通函数不能声明为虚函数。
2)静态成员函数不能是虚函数
静态成员函数不受对象的捆绑,只有类的信息。
3)内联函数不能是虚函数
4)构造函数不能是虚函数
构造时,对象的创建尚未完成。构造完成后,才能算一个名符其实的对象。
5)析构函数可以是虚函数且通常声明为虚函数。
补充:
构造函数为什么不能是虚函数?
虚函数是相应一个指向
vtable
虚函数表的指针,这大家都知道,但是这个指向vtable
的指针事实上是存储在对象的内存空间的。问题出来了,假设构造函数是虚的。就须要通过vtable
来调用。但是对象还没有实例化,也就是内存空间还没有,怎么找vtable
呢?所以构造函数不能是虚函数。( 从实现上看,
vtable
虚函数表在构造函数调用后才建立,因而构造函数不可能成为虚函数;)