類繼承中建構函式和析構函式地呼叫

2021-08-25 12:34:37 字數 2629 閱讀 2988

繼承 建構函式 析構函式

類繼承中建構函式和析構函式的呼叫

現在,有三個類,類的定義如下

class ca

這個程式執行結果是

ca constructor

cb constructor

cc constructor

cc desstructor

cb desstructor

ca desstructor

靠,太簡單了,乙個雞蛋飛過來了,:(

繼續……………………

(2) 再做第二個試驗之前,先做一點小小修改

~ca()

yeah

結果一模一樣哦

ca constructor

cb constructor

cc constructor

cc desstructor

cb desstructor

ca desstructor

但是如果把virtual ~ca()

執行結果

ca constructor

cb constructor

cc constructor

cc desstructor

cb desstructor

ca desstructor

取消ca中的虛析構函式,那麼,ca,cb,cc中沒有虛析構函式

那麼3中**執行結果如下

ca constructor

cb constructor

cc constructor

cb desstructor

ca desstructor

只調到cb的析構哦,

繼續試驗,ca,cb,cc中,只有cb是虛析構函式

3中**執行如下

ca constructor

cb constructor

cc constructor

cc desstructor

cb desstructor

ca desstructor

所以,如果是cb指向派生類,只要cb或者其基類中存在虛析構函式,那麼也是所有的析構函式都呼叫的了

繼續………………

(4)修改main **如下

int main()

如果a的析構函式是虛的,那麼情況如2,不多說了

如果是ca的析構函式不是虛的,而cb或者cc的析構函式是虛擬的,那麼在呼叫delete p;會出現記憶體錯誤

expression:_block_type_is_valid(phead->nblockuse)

是在釋放記憶體的時候出現這樣的錯誤

上網查了一下,_block_type_is_valid是用來檢測記憶體有效性巨集中的乙個,這個錯誤說明指標使用出現了問題

後來想了一想,應該是因為繼承類中出現了虛函式,所以多了乙個指向虛函式表的指標,而基類中乙個虛函式都沒有,所以也沒有這個指標啦

所以在delete的時候就出現了記憶體錯,事實證明,這個猜想應該是站得住腳的,在ca中新增乙個虛函式,即使的空的虛函式,也不會出現記憶體錯,

關於這個問題,我想在下次繼續討論吧,這裡不深入進去了,

回到正題,在ca中新增乙個空的,任意的虛函式以後,執行正確了,

執行結果是

ca constructor

cb constructor

cc constructor

ca desstructor

這與(2)中的情況是一樣的,只要ca的析構函式不是虛擬的,就只能呼叫ca的析構了

最後來看一種非常bt的做法

(5)ca cb cc中的析構函式,誰是虛擬的,無所謂,隨便

修改main **如下

int main()

執行結果

ca constructor

cb constructor

cc constructor

下面呢???下面沒有了,暈……………………

這種情況,構造了乙個cc的物件,然後呢,沒有調析構函式,直接把申請的

記憶體釋放了,最好不要這樣用咯

好了,最後,上面,基本上把所有的,我能想到的情況都整理了一下,

總結一下:

如c1 * p = new c2();

delete p;

這樣的**

這裡,c1是c2的基類,c1可能是c2的爸爸,可能是爺爺,可能是爸爸的爺爺,可能是爺爺的爺爺…………………………

那麼首先,呼叫的建構函式是

從c2的第乙個祖先一直到c2………………。和c1是什麼沒關係

在delete p的時候,那麼有以下幾種情況:

1) c1或者c1的祖先(基類)中,含有虛析構函式,那麼呼叫的析構函式的順序是從c2一直到c2的第乙個祖先(#add最開始的祖先)

2)如果c1或者c1的祖先中,沒有乙個是類是含有虛析構函式的,那麼呼叫的是從c1一直到c1的(也是c2的)第乙個祖先的(#add表述有待細思)

3)如果c1是void,那就什麼析構都不呼叫了。

如果乙個類,作為多型的基類,那麼盡量把析構函式宣告成虛擬的,不然………………,

好了,就此打住吧,關於4中的記憶體錯誤,下次再談論吧,專案要開始了,又要忙了,哭去了……………………

參考書籍

《effective c++》

類繼承中建構函式和析構函式的呼叫

類繼承中建構函式和析構函式的呼叫 現在,有三個類,類的定義如下 class ca class cb public ca 這個程式執行結果是 ca constructor cb constructor cc constructor cc desstructor cb desstructor ca de...

類 建構函式和析構函式

一.類 類定義的變數就是物件 1.建構函式 只有 建立物件的時候系統自動呼叫的函式 初始化物件 1 建構函式名與類名相同 2 建構函式沒有返回值 3 建構函式可以過載 注意 關於建構函式 1 如果建構函式被呼叫了,則一定有乙個新物件被建立了 2 如果有乙個新物件被建立,則一定有乙個建構函式被呼叫了 ...

繼承中的構造和析構函式

子類物件在建立時首先會呼叫父類的建構函式,在父類的建構函式執行結束後,再執行子類的建構函式。當父類的建構函式有引數時,需要在子類的初始化列表中顯示呼叫。析構函式的呼叫的先後順序與建構函式相反 結論 建構函式 先呼叫父類 再呼叫子類 析構函式 先呼叫子類 再呼叫父類 如下所示 include usin...