我知道,對於存在虛函數的基類,一般需要將基類的析構函數定義為虛函數,從而實現資源的合理釋放,而且我也知道派生類在重載時,只需要清理自己的對象,不過,有時候還是會有些疑惑感,所以寫了一個簡單的例子,來消除疑惑。下面是實例內容:
#include <iostream> class student { public: student() {} ~student() { std::cout << "a student" << std::endl; } }; class bachelor { public: bachelor() {} ~bachelor() { std::cout << "a bachelor" << std::endl; } }; class studentHolder { public: studentHolder() { } virtual ~studentHolder() {} private: student st; }; class bachelorHolder : public studentHolder { public: bachelorHolder() : studentHolder() { } ~bachelorHolder() override { } private: bachelor bcl; };
下面是調用的地方的代碼:
#define _CRTDBG_MAP_ALLOC #include <stdlib.h> #include <crtdbg.h> int main() { _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF); studentHolder* holder = new bachelorHolder(); delete holder; return 0; }
這種情況下,會執行正確的清理操作:
這種情況下,如果將bachelorHolder中的析構函數刪除,即:
class bachelorHolder : public studentHolder { public: bachelorHolder() : studentHolder() { } private: bachelor bcl; };
這種情況下,對象依然被很好的清理,因為C++會默認為類創建一個析構函數,而且如果基類為虛函數,派生類創建的為重寫基類的虛函數。結果依然是:
如果在上述的情況下,將studentHolder析構函數的virtual移除,即:
class studentHolder { public: studentHolder() { } ~studentHolder() {} private: student st; };
結果將變成:
不過,注意一點,這里,只是說派生類的析構函數沒有被調用,資源(分配的堆內存)還是會被很好的釋放。這里,可以查看,如果我們將main函數中的delete holder;注釋掉:
int main() { _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF); studentHolder* holder = new bachelorHolder(); // delete holder; return 0; }
在debug模式下,進行調試,會在output窗口,得到如下結果:
而就算將main函數,改為如下:
int main() { _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF); studentHolder* holder = new bachelorHolder(); delete reinterpret_cast<void*>(holder); return 0; }
在output窗口,都不會出現內存泄漏的顯示。大致內容就是上述顯示,在有疑慮的時候,可以參考一下。