【已解決】刪除指向介面指標 (Interface pointer) 的物件不會執行解構函式 (Destructor)

一般物件在生命週期結束時,會呼叫解構函式,以便執行釋放資源的動作。但對於實作介面的物件,如果是以介面指標的方式來呼叫,竟然不會呼叫解構函式,Oh My God。讓我們一步一步來看看吧!

#include "stdafx.h"
#include <iostream>

using namespace std;

struct IAnimal {
 virtual void Eat() = 0;
};

class Dog : public IAnimal {
public:
 Dog() { cout << "Dog construct." << endl; }
 ~Dog() { cout << "Dog destruct." << endl; }
 void Eat() { cout << "Dog eat ..." << endl; }
};

int _tmain(int argc, _TCHAR* argv[])
{
   Dog* pDog = new Dog();

   pDog->Eat();

   delete pDog;

   return 0;
}


如果是這種方式,當然沒問題,結果如下:

Dog construct.
Dog eat ...
Dog destruct.

但如果改成這樣呢?

int _tmain(int argc, _TCHAR* argv[])
{
   IAnimal* pDog = new Dog();

   pDog->Eat();

   delete pDog;

   return 0;
}

執行結果如下,怎麼會變這樣呢?


Dog construct.
Dog eat ...


其實也合理,因為 IAnimal 本來就沒有 Destructor,那就加一個吧

struct IAnimal {
 virtual ~IAnimal() = 0;

 virtual void Eat() = 0;
};

很不幸地,編譯錯誤,因為 Destructor 跟一般函式不一樣,所以不能用 pure virtual function。再換一個方式

struct IAnimal {
 ~IAnimal() { cout << "IAnimal destruct." << endl; }

 virtual void Eat() = 0;
};

執行結果如下:


Dog construct.
Dog eat ...
IAnimal destruct.

好一點,不過還是沒呼叫物件的 Destructor,再加個 virtual 看看

struct IAnimal {
 virtual ~IAnimal() { cout << "IAnimal destruct." << endl; }

 virtual void Eat() = 0;
};

執行結果如下,終於達到我們的要求了!


Dog construct.
Dog eat ...
Dog destruct.
IAnimal destruct.


所以正式應用時,只要把 IAnimal destructor 改為 Null function 就可以了!!!

留言

這個網誌中的熱門文章

Linux 批次檔的寫法

【分享】如何顯示 Debug Message

[分享] Visual Studio 遠端偵錯