C++のインターフェースクラスを使う練習中です。
開発環境はVisual Studio Community 2015です。
1つのインターフェースクラス「IHoge」から派生される
2つのクラス「CHoge1」「CHoge2」があります。
各クラスの共通部分(インターフェース)を取得するためにGetIHoge関数を用意し、
ここではメモリをnewにより確保し、そのポインタを返します。
動作確認のために、「CHoge1」「CHoge2」それぞれのデストラクタにcoutを用意しました。
以下がそのコードです。
コード:
#include <iostream>
#include <memory>
/* Hogeインターフェースクラス */
class IHoge {
public:
//純粋仮想デストラクタ
virtual ~IHoge() = 0;
};
IHoge::~IHoge() {}
/* IHoge継承クラス1 */
class CHoge1 : public IHoge {
public:
virtual ~CHoge1() override {
std::cout << "デストラクタ:CHoge1" << std::endl;
}
};
/* IHoge継承クラス2 */
class CHoge2 : public IHoge {
public:
virtual ~CHoge2() override {
std::cout << "デストラクタ:CHoge2" << std::endl;
}
};
/* CHoge1,CHoge2のインターフェース取得用関数 */
IHoge* GetIHoge(int num) {
switch (num)
{
case 1:
return new CHoge1;
case 2:
return new CHoge2;
default:
return nullptr;
}
}
/* メイン */
int main() {
IHoge* pIHoge;
//CHoge2としてメモリ確保(引数に「2」を渡す)
if ((pIHoge = GetIHoge(2)) == nullptr)
return 1; //エラー
//解放
delete pIHoge;
return 0;
}
実行結果は、deleteされた時点で「デストラクタ:CHoge2」と出力され、
正常にCHoge2のデストラクタが呼ばれていることが確認できます。
そこで、インターフェースクラスの純粋仮想デストラクタが無かった場合、すなわち
コード:
/* Hogeインターフェースクラス */
class IHoge {
public:
//純粋仮想デストラクタ
//virtual ~IHoge() = 0; //←無かった場合
};
//IHoge::~IHoge() {} //実体もコメントアウト
/* IHoge継承クラス1 */
class CHoge1 : public IHoge {
public:
//virtual ~CHoge1() override {
~CHoge1() { //←通常のデストラクタに変更
std::cout << "デストラクタ:CHoge1" << std::endl;
}
};
/* IHoge継承クラス2 */
class CHoge2 : public IHoge {
public:
//virtual ~CHoge2() override {
~CHoge2() { //←通常のデストラクタに変更
std::cout << "デストラクタ:CHoge2" << std::endl;
}
};
各クラスに上記の変更を加えて実行すると、
deleteされた時点でCHoge2のデストラクタから何も出力されなくなりました。
つまりCHoge2のデストラクタが呼ばれていないように思います。
インターフェースクラスには無いものの継承クラス「CHoge1」「CHoge2」の中ではデストラクタを定義しているにもかかわらず、
なぜデストラクタが呼ばれなくなるのでしょうか。
CHoge2からIHogeインターフェースクラスにキャスト的なことが成されたために、
IHogeでデストラクタが定義されていない
→CHoge2のデストラクタが見えない(実行されない)
ということでしょうか。