[c++] delete 只有聲明沒有定義的指針時遇到的問題

今天遇到這樣一個問題:

class AParent 有一個成員 BParent* ptr 初始化爲 nullptr
class AChild 作爲 AParent 的子類,ptr = new BChild , 其中 BChild 是 BParent 的子類

爲了減少編譯時的依賴, AParent.h 上面聲明瞭 class BParent;
在 AParent.cpp 裏面雖然調用了 delete ptr, 但是並未在 AParent.cpp 裏面 include BParent.h

導致在 AParent.cpp 裏 delete ptr 時,會發現 既沒有走 BParent 的析構函數 ,也沒有走 BChild 的析構函數

站在編譯器的角度來看 , 由於 AParent.cpp 只有 BParent 的類聲明,並沒有類定義,所以 AParent.cpp 其實並不知道 delete ptr 時要走哪個析構函數。

這樣的代碼如果隱藏在比較複雜的系統裏,就可能會因爲少執行了許多析構函數,造成各種資源的泄漏。
解決的辦法也很簡單,只要在 AParent.cpp 頂上 incude BParent.h ,就可以讓 delete ptr 時呈正確的多態形式,執行到對應 BChild 和 BParent 的析構函數了。

我在想,如果編譯器在 delete ptr 時認爲在調用 BParent 的析構函數,從而直接報一個鏈接錯誤找不到 ~BParent() 的定義,就可以避免這樣的問題了。但是無論是 msvc 還是 xcode 的編譯器都沒有這樣做。可能是有更深層的原因。

通過這個問題,我要吸取2個教訓:
1.認識到 c++ 裏 delete 一個只有聲明、沒有定義的指針,無論是在編譯鏈接時,還是在運行時,都是不會有明確報錯的
2.需要注意的是在 .h 裏聲明瞭類,一定要記得在 cpp 裏面 include 對應的實現

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章