虛解構函式、虛擬函式考題
阿新 • • 發佈:2018-12-18
虛解構函式、虛擬函式結合考題變種
1.[Effective C++原則07]:為多型基類宣告virtual 解構函式。
[如果不]: 如果不宣告為解構函式,可能出現的結果如下:Derived物件的成分沒有被銷燬,形成資源洩露、在除錯上會浪費很長時間。
#include <iostream>
using namespace std;
class CSimpleClass
{
public:
CSimpleClass()
{
cout << "CSimpleClass" <<endl;
}
~CSimpleClass()
{
cout << "~CSimpleClass" << endl;
}
private:
};
class CDerived : public CSimpleClass
{
public:
CDerived()
{
cout << "CDerived" << endl;
}
~CDerived()
{
cout << "~CDerived" << endl;
}
private:
};
int main()
{
CSimpleClass *pSimple = **加粗樣式**new CDerived;
delete pSimple;
system("pause");
return 0;
}
執行結果如下:
顯然,CDerived
物件沒有被析構!
1、 造成上述不同的原因何在?
“C++標準”明確指出,當派生類物件經由一個基類指標pBaseObject被刪除,而該基類帶有一個non-virtual解構函式,其結果未有定義(即不可預知)。實際執行時,如上面第一個圖示,會產生bug,派生類的物件沒有被銷燬。 這就形成詭異的“區域性銷燬”物件,形成資源洩露。
2、 什麼時候需要基類解構函式宣告為虛擬函式?
什麼時候不需要基類的解構函式為虛擬函式?
該問題涉及解構函式何時應該為虛擬函式。注意:對於上面的基類BaseClass, 若解構函式不為虛擬函式,sizeof(BaseClass) = 1。 若解構函式為虛擬函式,sizeof(BaseClass) = 4。
2.[Effective 原則09]:絕不在構造和析構過程中呼叫virtual函式。 【原因】:base class的執行更早於derived class的建構函式,當base class的建構函式執行的時候derived class的成員變數尚未初始化。 【如果不】:執行的結果不會動態聯編,依然執行其所在層的虛擬函式。 3.綜合1,2的筆試題如下:
#include <iostream>
using namespace std;
class CBase
{
public:
CBase()
{
cout << "CBase ctor" << endl; foo();
} //呼叫本層的foo
~CBase()
{
cout<< "CBase dtor" << endl; foo();
} //未加virtual,且呼叫本層的foo
private:
virtual void foo(){ cout << "Base::foo()" << endl; } //
};
class CDerived : public CBase
{
public:
CDerived()
{
cout << "CDerived ctor" << endl; foo();
}
~CDerived()
{
cout << "CDerived dtor" << endl;
foo();
}
private:
virtual void foo()
{
cout << "Derived::foo()" << endl;
}
};
int main()
{
CBase*pBase = new CDerived;
delete pBase;
system("pause");
return 0;
}
顯然,1.CDerived的解構函式不會被呼叫,因為CBase的解構函式非虛擬函式。 2.在CBase的構造和解構函式中呼叫虛擬函式,僅會執行本層的定義,不會下調。還是遵照[Effective 原則09]:絕不在構造和析構過程中呼叫virtual函式為上策。