析構函式的奧秘

2021-08-25 20:47:34 字數 1318 閱讀 6660

請看如下一段**:

#include

using namespace std;

class a

~a()

private:

int *pvalue;

};class b

virtual ~b()

};class c : public b

virtual ~c()

private:

a a;

};int main(void)

類c從類b中繼承出來,類c中聚合了乙個類a的物件,類c的析構函式並未呼叫類a的析構函式,請問:這段**執行後,會呼叫類a的析構函式釋放記憶體嗎?經測試,執行結果如下:

constructor of b

constructor of a

constructor of c

deconstructor of c

deconstructor of a

deconstructor of b

由此可以看出,c的析構函式確實呼叫了類a的析構函式,該呼叫是由編譯器隱含加入的,隨後還呼叫了基類b的析構函式,但是請注意,編譯器只會為基類和聚合類新增對析構函式的呼叫,如果c中的成員為指向類a的指標,則編譯器不會加入對類a的析構函式的呼叫。

那麼,如果我們把main函式改變一下:

int main(int argc, char* argv)

請問:這段**會發生記憶體洩漏嗎?執行結果如下:

constructor of b

constructor of a

constructor of c

deconstructor of b

發生了什麼?呼叫了a的構成函式分配了記憶體,卻只呼叫了b的析構函式,c和a的析構函式都沒有呼叫,記憶體沒有釋放,為什麼?

有人也許已經看出了問題所在,b和c的析構函式都應該是虛函式,否則,由於b的型別為指向類b的指標,delete b只會呼叫b的析構函式。當b和c的析構函式都是虛函式時,編譯器會根據b指向的物件實際上是c的物件,而去呼叫c的析構函式。請對**作如下改變:

class b

//所有b的派生類的析構函式都將自動變為virtual型

};class c : public b // 此處virtual可有可無

private:

a a;

};再次執行,結果正確:

constructor of b

constructor of a

constructor of c

deconstructor of c

deconstructor of a

deconstructor of b

析構函式的奧秘

class b class c public b private a a int main int argc,char argv 類c從類b中繼承出來,類c中聚合了乙個類a的物件,類c的析構函式並未呼叫類a的析構函式,請問 這段 執行後,會呼叫類a的析構函式釋放記憶體嗎?經測試,執行結果如下 con...

C 析構函式 虛析構函式

1.為什麼要定義虛析構函式?如果有乙個帶有虛函式功能的類,則它需要乙個虛析構函式,原因如下 1 如果乙個類有虛函式功能,它經常作為乙個基類使用 2 如果它是乙個基類,它的派生類經常使用new來分配 3 如果乙個派生類物件使用new來分配,並且通過乙個指向它的基類的指標來控制,那麼它經常通過乙個指向它...

建構函式 析構函式 虛析構函式

說析構函式之前,先說下建構函式。建構函式用來完成對物件的一系列初始化操作,主要作用有 1.給建立的物件建立乙個識別符號 2.為物件資料成員開闢記憶體空間 3.完成物件資料成員的初始化 當並未顯示的定義建構函式時,會生成乙個預設的建構函式,預設建構函式不能完成物件資料成員的初始化,只能給物件建立一識別...