iT邦幫忙

2023 iThome 鐵人賽

DAY 11
0
自我挑戰組

Effective C++ 讀書筆記系列 第 11

[Day 11] Declare destructors virtual in polymorphic base classes

  • 分享至 

  • xImage
  •  

前言

今天的守則也跟前兩則有點關係,直接來看看~

記得把多型的base class destructor設為virtual!

這個守則是:

Declare destructors virtual in polymorphic base classes

不知道"polymorphic"=多型的話可以先了解一下,有在介紹它與virtual functions的整理很多~
現在的問題是,我們知道了多型的好用之處,也知道要記得把需要動態繫結的function設為virtual,但要切記的就是 destructor!! 當我們的base class有用到 virtual function,最好把destructor也設為virtual!

不設會有什麼後果呢?假設我們用base class的pointer來指向一個derived class的,那在delete這個pointer的時候,由於我們是用base class來保管它,它call的也會是base class的destructor。那問題就來了!如果base class的destructor是 non-virtual 的,那就只會call到這個base class的destructor,不會去call到derived class的destructor!這樣等於我們的delete不完全,例如只刪掉了base class的部分,derived class多餘的內容都沒清,會造成不預期的結果,也可能造成memory leak。

因此,此時就應該把base class的destructor設為virtual。例如:

class TimeKeeper{
public:
    TimeKeeper();
    ~TimeKeeper();
    virtual ~TimeKeeper(); // virtual destructor!
};

class AtomicClock: public TimeKeeper{...};

這樣,在destruct的時候就會知道需要去call derived class的destructor了。
總歸來說這類的動態base class多半都會有一些virtual functions,因為virtual的目的就是讓derived class可以在base class之上去implement一些客製化的內容。如果class裡面沒有任何virtual functions,那它可能其實不該是base class。而這些base class就需要virtual destructor,反之就不用。

作者要表達的是我們不該無限上綱,就把所有class的destructor都加virtual。因為virtual是有代價的,它需要另外存一個virtual table跟pointer來讓它知道現在需要call哪個function,所以也需要比較多空間;另外,傳出去別的程式語言他也沒辦法知道virtual動態繫結的部分。

以上其實可歸結為這句:

"若且唯若class內有virtual functions時,將destructor宣告為virtual宣告virtual的。

同理反過來說,當一個class它沒有virtual destructor的時候,就不該去繼承它!C++11之後也有了"final",可以宣告為final來確保這個class不能被繼承。

而還有一件需要注意的事!我們知道有 "pure virutal function" 的class是abstract class,它就是抽象的沒辦法被直接創來用,而其中一個簡單讓class變成抽象的方式就是讓它的destructor變成是pure virtual function!但重點來了!雖然它是pure virtual function,但我們仍需要定義它!!

了解原因就知道它的合理之處了。我們在destruct derived class的時候是先call derived class的destructor,然後是base class的destructor,這是跟其他一般function不一樣的地方,其他一般function override後base class的function就不會被call到,但destructor會;因為它會,所以它需要被定義,就是這麼簡單!

總結

貼心重點提醒:

  • Polymorphic base classes should declare virtual destructors. If a class has any virtual functions, it should have a virtual destructor.
  • Class not designed to be base classes or not designed to be used polymorphically should not declare virtual destructors.

參考資料


上一篇
[Day 10] Explicitly disallow the use of compiler-generated functions you do not want
下一篇
[Day 12] Prevent exceptions from leaving destructors
系列文
Effective C++ 讀書筆記30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言