虛析構函式 虛函式考題

2021-08-30 10:56:58 字數 2398 閱讀 4375

1.[effective c++原則07]:為多型基類宣告virtual 析構函式。

[如果不]: 如果不宣告為析構函式,可能出現的結果如下:derived物件的成分沒有被銷毀,形成資源洩露、在除錯上會浪費很長時間。

#include 

using namespace std;

class

c******class

~c******class()

private:}

;class

cderived

:public c******class

~cderived()

private:}

;int

main()

執行結果如下:

顯然,cderived物件沒有被析構!

1、 造成上述不同的原因何在?
「c++標準」明確指出,當派生類物件經由乙個基類指標pbaseobject被刪除,而該基類帶有乙個non-virtual析構函式,其結果未有定義(即不可預知)。實際執行時,如上面第乙個圖示,會產生bug,派生類的物件沒有被銷毀。

這就形成詭異的「區域性銷毀」物件,形成資源洩露。

2、 什麼時候需要基類析構函式宣告為虛函式?

什麼時候不需要基類的析構函式為虛函式?

該問題涉及析構函式何時應該為虛函式。注意:對於上面的基類baseclass,

若析構函式不為虛函式,sizeof(baseclass) = 1。

若析構函式為虛函式,sizeof(baseclass) = 4。

至於為什麼包含建構函式、非虛析構函式的類的大小為1個位元組。解釋如下:

空類類的大小比如baseclass沒有構造、析構函式,本來sizeof(baseclass)應該為0,但是我們宣告該型別例項的時候,必須在記憶體中占用一定的空間,否則無法使用這些例項。至於占用多少記憶體,由編譯器決定,visual studio中每個空型別的例項占用1個位元組的空間。

而加上建構函式、析構函式或其他非虛型別的函式以後呢?由於這些非虛型別的函式的位址只與類有關,而與類的例項無關,編譯器不會因為非虛函式的增加而新增任何額外的資訊。

那麼為什麼析構函式變成虛函式後,大小就變成4個位元組了呢?主要原因是:c++一旦發現類中有虛函式,就會為該類生成虛函式表,並在該型別的每乙個例項中新增指向虛函式表的指標。在32位機器上,乙個指標佔4個位元組的空間,所以求sizeof大小為4。而在64位機器上,乙個指標占用8個位元組的空間,因此sizeof大小為8。

即為類析構函式宣告為虛析構函式是以付出記憶體為代價的。所以,無端將所有類的析構函式宣告為虛函式,就向從未宣告它們是虛函式一樣,都是錯誤的。

總結如下:

(1)帶多型性質的基類應用宣告乙個虛析構函式。如果類中帶有任何虛函式,它就應該擁有乙個虛析構函式;

(2)設計類的目的如果不作為基類,或者不是為了具備多型性,就不應該宣告虛析構函式。

——參考《effective c++》條款7;《劍指offer》

2.[effective 原則09]:絕不在構造和析構過程中呼叫virtual函式。

【原因】:base class的執行更早於derived class的建構函式,當base class的建構函式執行的時候derived class的成員變數尚未初始化。

【如果不】:執行的結果不會動態聯編,依然執行其所在層的虛函式。

3.綜合1,2的筆試題如下:

#include

using namespace std;

class cbase

//呼叫本層的foo

~cbase()

//未加virtual,且呼叫本層的foo

顯然,1.cderived的析構函式不會被呼叫,因為cbase的析構函式非虛函式。

2.在cbase的構造和析構函式中呼叫虛函式,僅會執行本層的定義,不會下調。還是遵照[effective 原則09]:絕不在構造和析構過程中呼叫virtual函式為上策。

C 虛析構函式 純虛析構函式

虛析構函式 析構函式的工作方式是 最底層的派生類 most derived class 的析構函式最先被呼叫,然後呼叫每乙個基類的析構函式。因為在c 中,當乙個派生類物件通過使用乙個基類指標刪除,而這個基類有乙個非虛的析構函式,則結果是未定義的。執行時比較有代表性的後果是物件的派生部分不會被銷毀。然...

C 虛析構函式 純虛析構函式

虛析構函式 析構函式的工作方式是 最底層的派生類 most derived class 的析構函式最先被呼叫,然後呼叫每乙個基類的析構函式。因為在c 中,當乙個派生類物件通過使用乙個基類指標刪除,而這個基類有乙個非虛的析構函式,則結果是未定義的。執行時比較有代表性的後果是物件的派生部分不會被銷毀。然...

C 虛析構函式 純虛析構函式

虛析構函式 析構函式的工作方式是 最底層的派生類 most derived class 的析構函式最先被呼叫,然後呼叫每乙個基類的析構函式。因為在c 中,當乙個派生類物件通過使用乙個基類指標刪除,而這個基類有乙個非虛的析構函式,則結果是未定義的。執行時比較有代表性的後果是物件的派生部分不會被銷毀。然...