首先明確兩點
建構函式不可能定義為虛函式
虛函式的目的是通過父類引用或者指標呼叫子類的成員函式。而建構函式的目的是建立物件。建立子類物件時,將呼叫子類的建構函式,而不是父類的建構函式。子類的建構函式將使用父類的乙個建構函式。這種順序不同於繼承機制。因此,子類不繼承父類的建構函式,所以將類的建構函式宣告為虛函式沒有意義。這個如果不能理解,記住就好了。
父類的析構函式應該是虛函式
關於第二點,舉個例子
a是父類,b是a的子類,在b中還新增了乙個char* name成員,name指向一塊由new申請的記憶體。當b類的物件被銷毀是,必然會呼叫~b()析構函式來釋放記憶體。請看下面**:
如果,a 的析構函式沒有宣告為虛函式,那麼delete a使用預設的靜態聯編,也就是呼叫a的析構函式~a();這將會釋放掉b類中a部分指向的記憶體,但是不會釋放新的類成員指向的記憶體,也就是b的name成員指向的記憶體塊,這樣就造成記憶體洩漏的問題。但是如果a的析構函式宣告為虛函式,那麼b的虛函式表中會把指向a的析構函式的指標位置改為指向b的析構函式。此時呼叫delete a就會呼叫b的析構函式,釋放掉由b指向的記憶體,然後呼叫a的析構函式,釋放由a指向的記憶體。a* a = new b;
...delete a; //此時呼叫哪個析構函式,~a()還是~b();
空口無憑,來個例子看看再說。
可見僅僅執行了a的析構函式,釋放掉了a指向的記憶體,但是b指向的記憶體沒有被釋放掉。#includeusing namespace std;
class a {
public:
~a() {
cout<<"a::~a()"《這段**執行結果:
a::~a()
我們把a的析構函式宣告為虛函式
程式先呼叫子類的析構函式,釋放掉b指向的記憶體,然後呼叫父類的析構函式,釋放掉a指向的記憶體。virtual ~a() {
cout<<"a::~a()"《再次執行,結果如下:
b::~b()
a::~a()
C 析構函式 建構函式 虛函式關係
析構函式 destructor 也是乙個特殊的成員函式,它的作用與建構函式相反,它的名字是類名的前面加乙個 符號。在c 中 是位取反運算子,從這點也可以想到 析構函式是與建構函式作用相反的函式。當物件的生命期結束時,會自動執行析構函式。具體地說如果出現以下幾種情況,程式就會執行析構函式 如果在乙個函...
建構函式 析構函式 虛析構函式
說析構函式之前,先說下建構函式。建構函式用來完成對物件的一系列初始化操作,主要作用有 1.給建立的物件建立乙個識別符號 2.為物件資料成員開闢記憶體空間 3.完成物件資料成員的初始化 當並未顯示的定義建構函式時,會生成乙個預設的建構函式,預設建構函式不能完成物件資料成員的初始化,只能給物件建立一識別...
關於建構函式 析構函式和虛函式的關係
建構函式不能宣告為虛函式的原因是 解釋一 所謂虛函式就是多型情況下只執行乙個,而從繼承的概念來講,總是要先構造父類物件,然後才能是子類物件,如果建構函式設為虛函式,那麼當你在構造父類的建構函式時就不得不顯示的呼叫構造,還有乙個原因就是為了防錯,試想如果你在子類中一不小心重寫了個跟父類建構函式一樣的函...