C 為多型基類宣告virtual析構函式

2022-10-11 05:42:07 字數 2266 閱讀 5255

來自《effective c++》條款07:為多型宣告virtual析構函式

當derived class物件經由乙個base class指標被刪除,而該base class帶著乙個non-virtual析構函式,其結果未有定義——實際執行時通常發生的是物件的derived成分沒被銷毀,而其基類成分通常會被銷毀,於是造成了乙個詭異的「區域性銷毀」物件。

解決這個問題的做法很簡單:給base class乙個virtual析構函式。此後刪除derived class物件就會如你想要的那般銷毀整個物件。

當class不企圖被當作base class,令其析構函式為virtual往往是個餿主意。許多人的心得是:只有當class內含至少乙個virtual函式,才能為它宣告virtual析構函式。

有時候令class帶乙個pure virtual析構函式,可能頗為遍歷,pure virtual函式導致abstract classes——也就是不能被實體化的class。也就是說不能為那種型別建立物件。然而當你希望擁有抽象class,但手上沒有任何pure function時就可以將把希望抽象成的那個class宣告為乙個pure virtual析構函式。下面是個例子:

class

awov ;

這個class有乙個pure virtual函式,所以它是乙個抽象class,又由於它有個virtual析構函式,所以你不必擔心析構函式的問題。然而這裡有個竅門:你必須為這個pure virtual析構函式提供乙份定義:

awov::~awov() {}

析構函式的運作方式是,最深層派生的那個class其析構函式最先被呼叫,然後是其每乙個base class的析構函式被呼叫。編譯器會在awov的derived classes的析構函式中建立乙個對~awov的呼叫動作,所以你必須為這個函式提供乙份定義。如果不這樣做,聯結器會發出抱怨。  

請記住:

1. polymorphic(帶多型性質的)base classes應該宣告乙個virtual析構函式。如果class帶有任何virtual函式,它就應該擁有乙個virtual析構函式。

2. classes的設計目的如果不是作為base classes使用,或不是為了具備多型性(polymorphically),就不該宣告virtual析構函式。

要分析為什麼沒有將基類的析構函式宣告為virtual,只有基類部分會被銷毀呢?這要首先明白c++中的名字查詢與繼承。理解函式呼叫的解析過程對於理解c++的繼承至關重要,假設我們呼叫p->mem()(或者obj.mem()),則依次執行以下4個步驟:

1.首先確定p(或obj)的靜態型別。因為我們呼叫的是乙個成員,所以該型別必然是類型別。

2. 在p(或obj)的靜態型別對應的類中查詢mem。如果找不到,則依次在直接基類中不斷查詢直到到達繼承鏈的頂端。如果找遍了該類及其基類仍然找不到,則編譯器將報錯。

3. 一旦找到了mem,就進行常規的型別檢查以確認對於當前找到的mem,本次呼叫是合法的。

4. 假設呼叫合法,則編譯器將根據呼叫的是否是虛函式而產生不同的**:

——如果mem是虛函式且我們是通過引用或指標進行進行的呼叫,則編譯器產生的**將在執行時確定到底執行該虛函式的哪個版本,一句是物件的動態型別。

——如果mem不是虛函式或者我們是通過物件(而非引用或指標)進行的呼叫,則編譯器將產生乙個常規函式呼叫。

通過物件呼叫虛函式時,呼叫哪個類的函式取決於物件的型別。物件型別是基類時,就呼叫基類的函式;物件型別是子類時,就呼叫子類的函式。

使用指標訪問非虛函式時,編譯器根據指標本身的型別決定要呼叫哪個函式,而不是根據指標指向物件型別。

使用指標訪問虛函式時,編譯器根據指標所指物件的型別決定要呼叫哪個函式,而與指標本身型別無關。

可以看到如果我們將基類的指標指向動態分配的子類物件,而基類的析構函式沒有宣告為虛函式,那麼按照名字查詢就不會呼叫到派生類的析構函式。

C 為多型基類宣告virtual析構函式

20180306 c 為多型基類宣告virtual析構函式 記錄時間的基類和派生類 class timekeeper class atomicclock public timekeeper 原子鐘 class waterclock public timekeeper 水鐘 class wristwa...

為多型基類宣告virtual析構函式

書籍 effective c 中的條款7 讀書筆記 條款7的內容,可以大致總結為下面幾個問題 問題1 什麼是多型基類?問題2 為什麼要把多型基類的析構函式宣告為virtual析構函式?問題3 是不是應該把所有的類的析構函式宣告為virtual函式?下面來詳細回答上面三個問題 問題1 什麼是多型基類?...

為多型基類宣告virtual析構函式

一 中心內容 1 polymorphic 帶多型性質的 base classes應該宣告乙個virtual析構函式。如果class帶有任何virtual函式,它就應該擁有乙個virtual析構函式 2 classes的設計目的如果不是作為base classes使用,或不是為了具備多型性,就不該宣告...