ページ 11

派生クラスへのポインタが勝手にNULLになる

Posted: 2013年8月13日(火) 02:17
by hart
こんばんは。
今までC言語とDXライブラリを用いて、ゲームを作成してきたのですが、
オブジェクト指向の勉強をしてみたいと思い、C++で何かを書こうと思い立ちました。
今回は、ゲームの1要素である「エフェクト」を作ってみようとしました。

エフェクト全体を扱うクラスをmainでnewしたときに(そのコンストラクタで)、
実際のエフェクト(基本エフェクトクラスから派生)をnewし、
そのポインタを全体を扱うクラスのメンバのポインタmlpNowEffect(型は基本エフェクトクラス)に保持します。

この時(保持した瞬間)はそのポインタがしっかりと保持されているのですが、
全体を扱うクラスの別のメンバ関数をmainから呼んだときには、ポインタがNULLになっていて、
正常にその先を呼び出すことができません。

どこでNULLになっているのか、ブレークポイント等を設置して調べてみたのですが、見当がつかず。。。
助言を頂けないでしょうか?
ソースは以下です(要DXライブラリ)。ビルドが通るのは確認しています。
http://www1.axfc.net/uploader/so/2994046.zip
[DLパス]
cppeffect

環境は以下です。
・OS:Windows 8
・開発環境:Visual Studio 2012 Professional

また、C++のクラスの勉強用に書いたソースですので、クラスの構成や名前、機能などに
改良できる点などがあれば、指摘お願いいたします。

Re: 派生クラスへのポインタが勝手にNULLになる

Posted: 2013年8月13日(火) 02:40
by a5ua
【IEffect.hの抜粋】

コード:

	IEffect(int m) : mMode(m) , mlpNowEffect(NULL)  { //初期モード指定版コンストラクタ。
		mlpNowEffect = getLpNewEffect(mMode);
	}
	IEffect() { //コンストラクタ(オーバーロード)。IEffectクラスのインスタンスが生成されたときに呼ばれる
		IEffect(0);
	}
引数なしのコンストラクタで、引数ありのコンストラクタを呼んでいますが、これはおそらく意図した動作をしません。
IEffect(0);という記述は、IEffectクラスの一時オブジェクトを作成してすぐに破棄するだけだからです。

同じクラスの別のコンストラクタを使って初期化することはできない(C++11を除く)ので、
以下のように書く必要があります。
#多少冗長なので、mにデフォルト引数をつけるとかエフェクト作成部分を関数化するとか工夫の余地はあります

コード:

	IEffect(int m) : mMode(m) , mlpNowEffect(NULL)  { //初期モード指定版コンストラクタ。
		mlpNowEffect = getLpNewEffect(mMode);
	}
	IEffect() : mMode(0) , mlpNowEffect(NULL) { //コンストラクタ(オーバーロード)。IEffectクラスのインスタンスが生成されたときに呼ばれる
		mlpNowEffect = getLpNewEffect(mMode);
	}

Re: 派生クラスへのポインタが勝手にNULLになる

Posted: 2013年8月13日(火) 02:56
by hart
a5ua様、返信ありがとうございます。
なるほど。コンストラクタの中で別の同じクラスのコンストラクタを呼ぶと、
オブジェクトが一時的に生成されて破棄されるだけの動作になってしまうのですね。
疑問が解決しました。

コンストラクタ部分は、

コード:

	IEffect(int m=0) : mMode(m) , mlpNowEffect(NULL)  { //初期モード指定版コンストラクタ。
		mlpNowEffect = getLpNewEffect(mMode);
	}
とする(デフォルト引数を指定する)ことで冗長性をカットしました。
このように変更した後、ビルドし、正常に動作することを確認しました。
このトピックは解決とさせていただきます。
しかし、C++の勉強も兼ねているので、そちらの面でのアドバイス等がありましたら、
ぜひご教示ください。

ありがとうございました。