问题
什么时候该定义虚析构函数,为什么要这么做?
回答
当你通过一个基类指针去删除(delete)派生对象的时候,虚析构函数就很用了。
代码语言:javascript复制#include <iostream>
using namespace std;
class Base
{
public:
Base(){
cout << "Base Constructor Calledn";
}
~Base(){
cout << "Base Destructor calledn";
}
};
class Derived1: public Base
{
public:
Derived1(){
cout << "Derived constructor calledn";
}
~Derived1(){
cout << "Derived destructor calledn";
}
};
int main()
{
Base *b = new Derived1();
delete b;
}
注意,我并没有把类 Base
的析构函数定义为虚(virtual)。输出如下:
Base Constructor Called
Derived constructor called
Base Destructor called
我们发现派生类的析构函数并没有调用,这是有问题的,有可能会造成内存泄漏,而解决这个问题的办法就是将 Base 的析构函数定义为虚(virtual),
代码语言:javascript复制class Base
{
public:
Base(){
cout << "Base Constructor Calledn";
}
virtual ~Base(){
cout << "Base Destructor calledn";
}
};
输出如下:
代码语言:javascript复制Base Constructor Called
Derived Constructor called
Derived destructor called
Base destructor called
总结起来就是:当你的程序满足以下任何一项时,都无需定义基类虚拟析构函数,否则你就应该定义为虚,
- 这个基类没有派生类
- 不在堆(heap)内存实例化
- 没有指向派生类的基类指针或引用
对于 1,还是很常见的,有的时候我们只是单纯的写一个类,并没有派生它的打算,那这个时候就无需将它的析构函数定义为虚(virtual)了。
对于 2,基本上是个工程项目都不太可能,哪有一次都不在堆(heap)上实例化对象的,我是没遇到过,肯定是有一些对象必须要堆上实例化的。
对于 3,基本上也不太可能,派生类的存在基本上都会用到它的基类指针和引用。