今天的守則也跟前兩則有點關係,直接來看看~
這個守則是:
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.