Effective C++ 條款07:為多型基類宣告virtual解構函式
阿新 • • 發佈:2021-06-25
前面的鋪墊有點多= =
我們考慮這樣一種情況:有很多種計時方法,比如原子計時,水滴計時等。我們試圖抽象出一個基類計時類,然後其他方法的計時器繼承這個類。設計如下
class TimeKeeper{
public:
TimeKeeper();
~Timekeeper();
};
class AtomicClock: public TimeKeeper{}; // 原子鐘
class WaterClock: public Timekeeper{}; // 水滴鍾
class WristWatch: public TimeKeeper{}; // 腕錶
這裡需要一點設計模式的知識:工廠方法模式。這是一個建立型設計模式,為了簡化建立多個同質(繼承與同一基類)的問題。這裡不細說了,可以先了解一下工廠方法模式。
我們建立了一個工廠函式用於生成這些類的物件
TimeKeeper* getTimeKeeper();
工廠方法返回的是一個基類指標,指向派生類的物件。很顯然,這個派生類的物件是被工廠方法new出來的,放在了heap儲存區。
那麼使用者就需要考慮delete掉這個指標的問題。我們試圖讓使用者記住某些一定要執行的操作(delete),這不是一個好的設計,因為使用者極可能忘記。
更嚴重的問題是,這個程式碼有一個非虛解構函式。在派生類被delete的時候,會呼叫物件的解構函式。這裡我們用的是基類的指標delete,那麼基類部分的記憶體肯定被釋放掉了。那派生類的部分被delete了嗎?由於基類的解構函式是個非虛的,基類的指標就無法動態繫結到派生類的解構函式上。因此delete基類,只能呼叫基類的解構函式,無法呼叫派生類的解構函式。假設我們的派生類裡有指標並且動態分配了記憶體,這就會導致記憶體洩露
如果我們不希望一個類被繼承,最好不要設計一個虛解構函式。因為將函式設定為虛的,C++會多給他整一個虛指標和虛表。這樣可能會導致不同機器上的相容性問題。如無必要,勿增實體。
並非所有的基類設計都是為了多型用途的。這些類就不需要虛的解構函式。