析構函式在什麼情況下應該宣告為虛函式

2021-10-19 17:23:45 字數 1692 閱讀 2732

如標題所言,乙個c++物件的析構函式,在什麼情況下,應該被宣告為乙個虛函式呢?

(看到這一標題,我興趣大增。)

首先,虛析構函式是什麼意思呢?well,你想想,乙個類的虛方法是什麼意思,就能明白虛析構函式是怎麼一回事兒了。

如果乙個方法被宣告為虛方法,則當呼叫這個方法時,會呼叫具體實現此方法的物件方法,也稱動態繫結。

如果這個方法不是虛方法,則會呼叫在編譯期指標確定的物件方法,這種稱之為:靜態繫結。

我們看看下面的例子:

對p->f()的呼叫會導致對sample::f的呼叫,因為指標的型別是指向sample物件的指標。雖然指標實際指向的derivedd物件,但因為指標的型別是sample指標,所以對於非虛方法f來說,會呼叫基類sample的f方法。

另一方面,對p->vf()的呼叫會導致對derived::vf的呼叫,因為vf為虛方法,屬於會呼叫派生類的f。

所以,現在應該理解什麼是虛方法了吧?

虛析構函式也和上面的原理一樣,只是通常你不會主動呼叫它。實際上它是在物件離開作用域或者你刪除物件時自動被執行的。如下圖所示:

因為sample並沒有宣告它的析構函式為虛函式,所以delete pp將呼叫指標本身的型別對應的物件的析構函式(sample::~sample),而不是派生類的析構函式(derived::~derived)。如你所看到的,這個行為在上面的**場景中,不是我們想要的。

通過上面的例項,你應該可以回答標題中提出的問題。

當符合如下兩個條件時,乙個類必須宣告它的析構函式為虛函式。

1) 你對這個類物件執行了delete。

2) 類指標可能指向乙個派生類物件。

有些人可能會說了:應該這樣說,只要乙個物件有宣告虛方法,則它就必須有乙個虛析構函式。

這種說法不正確。

下面我來舉乙個反例:下面的類沒有定義任何虛方法,但是它依然需要乙個虛析構函式。

delete p將會呼叫sample::~sample,而不是derived::~derived,導致了智慧型指標指向的stream物件的洩露。

下面是另外乙個例子:它定義了乙個虛方法,但是它並不需要乙個虛析構函式。

由於物件刪除是從與實際物件型別匹配的指標型別發生的,因此將呼叫正確的析構函式。這種模式通常發生在com物件中,com物件公開了與其介面相對應的幾種虛擬方法,但是物件本身是由其自己的實現而不是由基類實現的。(請注意,沒有任何com介面包含虛擬析構函式。)

知道何時使析構函式虛擬化的問題是,你必須知道人們將如何使用你的類。

如果c++有乙個」sealed」關鍵字,則規則將更簡單:如果執行」delete p」(其中p是指向未密封的類的指標),則該類需要乙個虛擬的析構函式。 (假想的」sealed」關鍵字是用來告訴編譯器:這個類可能作為另乙個類的基類)

什麼情況下,類的析構函式宣告為虛函式

include using namespace std class clxbase clxbase void dosomething class clxderived public clxbase clxderived void dosomething int main 執行結果 do someth...

析構函式什麼情況下要定義為虛函式

1.第一段 include using namespace std class clxbase clxbase void dosomething class clxderived public clxbase clxderived void dosomething int main 執行結果 do ...

C 建構函式和析構函式什麼情況下會用

析構函式 1.物件生命週期結束,被銷毀時 2.delete 指向物件的指標時 3.delete 指向基類物件的指標時,其析構函式是虛函式 4.在巢狀關係中,物件a是物件b的成員,當物件b執行析構函式時,物件a的析構函式也會被呼叫 建構函式 1.在宣告乙個普通物件的時候會呼叫建構函式 2.如果只是宣告...