ぼく用あれこれまとめ

仮想デストラクタ

最終更新:

bokuyo

- view
管理者のみ編集可

仮想デストラクタ

  • 仮想デストラクタの宣言の仕方はときにリンクエラーを引き起こし原因不明のままプロジェクト終了のお知らせを告げることがある.

仮想デストラクタって?

  • パパさんクラスを継承してこどもクラスを作ったときに、こどもクラスのデストラクタを呼んだつもりが、パパさんクラスのデストラクタが呼ばれちゃうことがある.
  • そこで、パパさんクラスのデストラクタが呼ばれる前に、こどもクラスのデストラクタも呼びたいので、パパさんクラスのデストラクタをオーバーライドしちゃう。
    • それが仮想デストラクタ。
  • 仮想デストラクタは仮想関数のお仲間さん。仮想関数には特殊な定義を書かなくてもいい関数があったよね。それが純粋仮想関数だったんだけども。
    • 仮想デストラクタにも純粋仮想デストラクタってのがあって、パパさんクラスでデストラクタの動きを書かずに、すべてこどもクラスに丸投げすることができたよね。
    • でもでも、ここでよく間違えちゃうのが、「"純粋"仮想デストラクタだから定義書かなくていいや!やっほーい!」って思っちゃうことなの!
    • 純粋仮想デストラクタの宣言の仕方をミスっちゃうとリンカエラーはかれて泣くことになるぞ!!


(純粋)仮想デストラクタの間違った宣言の仕方

class IListener
{
public:
	virtual ~IListener() = 0;          //←まずこれ。「error LNK2001: 外部シンボル は未解決です。」って言われた後に
				           //「fatal error LNK1120: 外部参照 1 が未解決です。」って言われる.
	virtual ~IListener();              //←同様にこれも。上記と同じエラーが吐かれる.
	virtual ~IListener() = 0;
	virtual ~IEventListener(){;} = 0;  //もちろんこんなのもコンパイルエラー.
};

正しい(純粋)仮想デストラクタの宣言の仕方


class IEventListener
{
public:
	virtual ~IEventListener() = 0
	{
		;                         //純粋仮想コンストラクタも定義を書かねばならない.
	}
	virtual ~IEventListener() = 0
	{
		return;                   //return;つけてもいけるっぽい.
	}
	virtual ~IEventListener() = 0 {}  //こんなのもいけちゃう.
};

// IActor.cpp ----------
#include "IActor.h"

	//ソースファイル中に定義を書いてもおっけー
IEventListener::~IEventListener()
{
}
  • 純粋仮想デストラクタは特殊で、定義を書かなければいけない。
    • 理由は知らないから今度規格を見てみることにする。
  • ちなみに純粋仮想デストラクタだけでなく、純粋仮想関数も定義を書くことができる。詳しくはEffective C++ 34項を参照せよ!
    • だって疲れたんだもん><

error LNK2001

  • error LNK2001で外部シンボルの派生クラスのデストラクタが未解決、と出るときは、継承元の仮想デストラクタの定義を見直した方がいいね。
  • とくに純粋仮想デストラクタを純粋仮想関数と同じものだと考えてると、定義を書き忘れてコンパイルエラーまで吐かれないから厄介。
.
記事メニュー
目安箱バナー