虛函數與多態一文中講了虛函數的用法和要點,但少講了一點,就是虛函數在析構中的用法,本文就是修復一bug的。
C++類有繼承時,析構函數必須爲虛函數。如果不是虛函數,則使用時可能存在內在泄漏的問題。
假設我們有這樣一種繼承關係:
如果我們以這種方式創建對象:
SubClass* pObj = new SubClass();
delete pObj;
不管析構函數是否是虛函數(即是否加virtual關鍵詞),delete時基類和子類都會被釋放;
如果我們以這種方式創建對象:
BaseClass* pObj = new SubClass();
delete pObj;
- 若析構函數是虛函數(即加上virtual關鍵詞),delete時基類和子類都會被釋放;
- 若析構函數不是虛函數(即不加virtual關鍵詞),delete時只釋放基類,不釋放子類;
測試代碼
大家可以自己測試一下,以下是我的測試代碼:
#include <string>
#include <iostream>
class BaseClass
{
public:
BaseClass()
: m_pValue(NULL)
{
}
/*virtual */~BaseClass()
{
delete m_pValue;
m_pValue = NULL;
std::cout << "BaseClass virtual construct." << std::endl;
}
void SetValue(int v)
{
if (!m_pValue)
{
m_pValue = new int(v);
}
else
{
*m_pValue = v;
}
}
private:
int* m_pValue;
};
class SubClass : public BaseClass
{
public:
SubClass()
: BaseClass()
, m_pstrName(NULL)
{
}
/*virtual */~SubClass()
{
delete m_pstrName;
m_pstrName = NULL;
std::cout << "SubClass virtual construct." << std::endl;
}
void SetName(const std::string& name)
{
if (!m_pstrName)
{
m_pstrName = new std::string(name);
}
else
{
*m_pstrName = std::string(name);
}
}
private:
std::string* m_pstrName;
};
int main()
{
BaseClass* pObj = new SubClass();
pObj->SetValue(10);
((SubClass*)pObj)->SetName("zhangsan");
delete pObj;
pObj = NULL;
return 0;
}