ページ 11

インスタンスをリサイクルするのはスマートではないでしょうか?

Posted: 2013年2月25日(月) 00:04
by taketoshi
こんばんわ。

プログラミングの設計についてお尋ねしたいことがあります。
敵クラスや弾丸クラス等、同じようなオブジェクトを複数扱うとき
敵や弾丸が消滅したらインスタンスもdeleteするべきなのでしょうか?
パラメータ関係を再度初期化してリサイクルし出現させるって方法はあまりスマートではない気がしています。

このようなプログラムを組むとき、敵や弾丸にそってインスタンスも消滅させ
次に出現するときはインスタンスを作り直すのがよいのか

どちらの方が設計的に理にかなっているのかご指導ください。

Re: インスタンスをリサイクルするのはスマートではないでしょうか?

Posted: 2013年2月25日(月) 00:12
by h2so5
インスタンスを作り直すように設計したほうが簡単だと思います。

Re: インスタンスをリサイクルするのはスマートではないでしょうか?

Posted: 2013年2月25日(月) 00:25
by softya(ソフト屋)
私も簡単でバグの減る方はどっちかで考えるべきだと思います。
画像ハンドルを保持している場合は、画像ハンドルは別クラスで管理しましょう。

Re: インスタンスをリサイクルするのはスマートではないでしょうか?

Posted: 2013年2月25日(月) 10:20
by beatle
newでインスタンスを作りなおすと、素直で分かりやすくなるけどnewのせいで遅くなる
インスタンスを再度初期化して使いまわすと、newを使わない分速くなるけど分かりにくくなる

というので悩んでいるのであれば、配置newを検討してみてはいかがでしょうか。
普通のnewを使うときの分かりやすさと、newを使わない速さを両立できるのではと思います。

インスタンスを使いまわすときは、恐らくインスタンスの配列があって、その配列の中から現在使われていないインスタンスを探し、そのインスタンスを再初期化して使うんですよね。
この過程のうち「再初期化」の部分を配置newでやるわけですね。

配置newは、メモリ領域を新たに確保せず、既に存在するメモリ領域にインスタンスを配置します。
普通のnewは、new自身がmallocで確保した領域にコンストラクタを適用するのに対して、配置newは、ユーザーが指定した領域にコンストラクタを適用するものです。

Re: インスタンスをリサイクルするのはスマートではないでしょうか?

Posted: 2013年2月25日(月) 23:55
by taketoshi
皆さん返信ありがとうございます。
一般的な指針が理解できました。

>>beatleさん
こういった手法もあるんですね。勉強になります。

>インスタンスを使いまわすときは、恐らくインスタンスの配列があって
今までこういった手法でやっていたので、配置newの概念も理解できました。

ありがとうございます。解決とさせていただきます。

Re: インスタンスをリサイクルするのはスマートではないでしょうか?

Posted: 2013年2月26日(火) 21:16
by taketoshi
すいません、ひとつ質問があります

softyaさんの発言に対してなのですが
>画像ハンドルを保持している場合は、画像ハンドルは別クラスで管理しましょう。

これはどのように実現すればよいでしょうか。
サンプルを書き出してみたのですがDraw関数のところで、ハンドル名を直指定してしまっているため
キャラクタークラスを作っても同じ画像が表示されるようにしか書き出せませんでした。

main関係は省略しています

コード:

//キャラクター定義構造体
typedef struct CharcterData{
	string szName;
	int HitPoint;
	int Move;
}CharData;


//キャラクター仮想クラス
class CharBase : public Task{
protected:
	int nPos_x;//ウインドウ座標
	int nPos_y;//ウインドウ座標
	int nScreenPos_x;//スクリーン座標
	int nScreenPos_y;//スクリーン座標
	int nDirection;
	bool bWalkFlag;
	int nHandle;
public:
	CharBase(){};
	~CharBase(){};
	virtual int Updata() = 0;
	virtual int Draw() = 0;
};

//キャラクタ画像管理クラス
class CharImage : public CharBase{
public:
	static void LoadHandle();
	static int nGraph[9];//子クラスを破棄しても画像を再読み込みしないようにここでstaticにしておく
};

//キャラクタークラス
class Charcter : public CharImage{
private:
	CharData cd;
public:
	Charcter(){};
	Charcter(CharData);
	~Charcter(){};
	int Draw() override;
	int Updata() override;
	static void CharProcedure(Charcter *);
};


//描写関数
int Charcter::Draw(){
	DrawGraph(nPos_x - nScroll_x,nPos_y - nScroll_y,nGraph[0],true);//これだと同じ画像しか表示できない・・どのように多態性をもたせればよいですか・・?
	return 0;
}

Re: インスタンスをリサイクルするのはスマートではないでしょうか?

Posted: 2013年2月26日(火) 21:29
by softya(ソフト屋)
これは、グラフィックハンドル自体を管理するクラスを作成すると言うことですね。
グラフィックハンドルが必要な時は、その管理クラスに対してグラフィックハンドルを要求します。
そうすれば、Charcterなどそれぞれのクラスがグラフィックハンドルの破棄や管理をする必要はなくなります。

Re: インスタンスをリサイクルするのはスマートではないでしょうか?

Posted: 2013年2月26日(火) 23:08
by taketoshi
アドバイスありがとうございます。
しばらく理解できなかったのですが、少し考えているうちに頭の中でイメージできるようになりました。

以下のように要所を書き換えて、読み込み前にハンドルを要求する関数をかませました。
多態性を確保する一歩を踏み出せたかと感じています。

これに対して、STLのmapクラスを用いて、キーとペアにしてハンドルを返す関数を組みなおせば
キャラクター構造体に代入した数値から画像ハンドルを引き出せるプログラムが組めると考えています。

コード:

//キャラクタ画像管理クラス
class CharImage : public CharBase{
public:
	static void LoadHandle();
	static int nIshtar[9];
	int *ReturnHandle();
};

//ハンドルを返す。引数にキーを設定するように書き換えればok
int *CharImage::ReturnHandle(){
	return nIshtar;
}

//描写

int Charcter::Draw(){

	int *nHandle = ReturnHandle();

	DrawGraph(nPos_x - nScroll_x,nPos_y - nScroll_y,nHandle[0],true);
	return 0;
}
これで前に進めそうです。ありがとうございます。