在我真正理解虛析構(gòu)函數(shù)之前,差不多每隔一個(gè)月,我都要百度一下“虛析構(gòu)函數(shù)的作用”。因?yàn)槲以趯懸粋€(gè)類時(shí),總是不能確定是否應(yīng)該將其析構(gòu)函數(shù)寫為虛函數(shù)。直到某一天,我突然地就悟了。
事實(shí)上,虛析構(gòu)函數(shù),就是虛的析構(gòu)函數(shù),也就是析構(gòu)函數(shù)具有了虛函數(shù)的性質(zhì)。
有如下代碼:
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
會(huì)觸發(fā)類的析構(gòu)函數(shù),一定程度上,我們可以把它當(dāng)做調(diào)用類的析構(gòu)函數(shù)。那么delete pBase
就相當(dāng)于pBase->~CBase()
,此時(shí)調(diào)用的是CBase::~CBase()
,而CDerived::~CDerived()
未被調(diào)用,這造成了m_pBuffer
的內(nèi)存泄漏。
為了解決這個(gè)問題,我們可以設(shè)置CBase
的析構(gòu)函數(shù)為虛函數(shù)。由于虛函數(shù)的多態(tài)性,pBase->~CBase()
實(shí)際調(diào)用的就會(huì)是CDerived::~CDerived()
,而CDerived::~CDerived()
又會(huì)調(diào)用CBase::~CBase()
。所有的析構(gòu)函數(shù)都被調(diào)用了,就不再有內(nèi)存泄漏發(fā)生了。
解決因delete
基類指針導(dǎo)致的資源泄漏,這就是虛析構(gòu)函數(shù)的作用所在;而具有虛函數(shù)性質(zhì)的析構(gòu)函數(shù),這就是虛析構(gòu)函數(shù)的真相所在。
下面兩幅圖應(yīng)該可以幫助你更好地理解: