在我真正理解虚析构函数之前,差不多每隔一个月,我都要百度一下“虚析构函数的作用”。因为我在写一个类时,总是不能确定是否应该将其析构函数写为虚函数。直到某一天,我突然地就悟了。
事实上,虚析构函数,就是虚的析构函数,也就是析构函数具有了虚函数的性质。
有如下代码:
class CBase
{
public:
CBase() { m_pArray = new int[20]; }
~CBase() { delete [] m_pArray; }
private:
int* m_pArray;
};
class CDerived : public CBase
{
public:
CDerived() { m_pBuffer = new char[20]; }
~CDerived() { delete [] m_pBuffer; }
private:
char* m_pBuffer;
};
int main()
{
CBase* pBase = new CDerived;
delete pBase; // pBase->~CBase()
return 0;
}
我们知道,delete
会触发类的析构函数,一定程度上,我们可以把它当做调用类的析构函数。那么delete pBase
就相当于pBase->~CBase()
,此时调用的是CBase::~CBase()
,而CDerived::~CDerived()
未被调用,这造成了m_pBuffer
的内存泄漏。
为了解决这个问题,我们可以设置CBase
的析构函数为虚函数。由于虚函数的多态性,pBase->~CBase()
实际调用的就会是CDerived::~CDerived()
,而CDerived::~CDerived()
又会调用CBase::~CBase()
。所有的析构函数都被调用了,就不再有内存泄漏发生了。
解决因delete
基类指针导致的资源泄漏,这就是虚析构函数的作用所在;而具有虚函数性质的析构函数,这就是虚析构函数的真相所在。
下面两幅图应该可以帮助你更好地理解:
普通析构函数与虚析构函数