天天看點

07 為多态基類聲明虛析構函數一、多态基類為什麼要聲明虛析構函數二、為什麼多态基類中聲明為虛析構函數,派生類就會被析構?三、當class不企圖被當作base class,令其析構函數為virtual導緻的問題四、雜項

一、多态基類為什麼要聲明虛析構函數

當derived class對象經由一個base class指針被删除,而該bass class 帶着一個non-virtual吸狗善書,其結果未有定義——實際執行時通常發生的是對象的的derived成分沒有被銷毀。

二、為什麼多态基類中聲明為虛析構函數,派生類就會被析構?

  • 析構函數的運作方式:最深層派生的那個class其析構函數最先被調用,然後是其每一個base class的析構函數被調用。
  • 抽象類的析構函數聲明為純虛析構函數:若想擁有一個抽象類,但又沒有其他pure virtual 函數,可以将析構函數聲明為pure virual。因為抽象類一般是被用來做基類的,而基類應該有個虛析構函數(抽象類中有其他virtual函數)。但是注意,應該為抽象類的純虛析構函數做個實作,否則編譯器會報錯(編譯器會在derived class的析構中建立一個對base class析構函數的調用)。
  • 基類的指針指向派生類時,若基類的析構函數為虛函數,派生類的虛表中會重寫基類的析構函數,當通過基類的指針釋放派生類性别的對象時,調用的是派生類的析構函數,而派生類的析構函數中會調用基類的析構函數。雖然派生類的析構函數和基類的析構函數不同名,但是也會發生重寫。

三、當class不企圖被當作base class,令其析構函數為virtual導緻的問題

  • vptr(虛表指針):指向一個由函數指針構成的數組。
  • vtbl(虛表):每一個帶有virtual函數的class都有一個相應的vtbl。

    當對象調用某一virtual函數,實際被調用的函數取決于該對象的vptr所指的那個vtbl——編譯器在其中尋找适當的函數指針。

    32位系統中,指針占4個位元組,64位系統中,指針占8個位元組。當class中包含virtual函數時,對象的大小會增加4~8個位元組。這會導緻c++對象不再和其他語言(如C)有着相同的結構。不能把c++對象傳至(或接受自)其他語言所寫的函數。

四、雜項

  • 并非所有的base classes設計目的都是多态用途,如标準string和STL容器都不被設計作為base classes使用,更别提多态了。
  • 某些class的設計目的是作為bass class使用,但不是為了多态用途。如标準程式庫的input_iterator_tag和被設計用來禁止使用預設生成的構造析構等函數的基類。

繼續閱讀