ループ内でのオブジェクトの動的確保について

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
あげだま

ループ内でのオブジェクトの動的確保について

#1

投稿記事 by あげだま » 3年前

STGを作っています。ボスの行動パターンをBossActionクラスという抽象クラス化し、そのクラスへのポインタスマートポインタ(bossaction)から派生の行動パターンをループ内で動的確保するプログラムを作っています。行動id(bs.act_id)によって行動パターンを場合分けするようにしているのですが、ループ内でそのまま確保すると延々と確保し続けてしまうので、idが切り替わった瞬間だけ確保するようにしなければならないと思い、typeidを使ってポインタがその行動パターンを指してない時のみ確保するように試みたのですが、実行してみると結局延々と確保し続けているようです。改善策を教えていただけると幸いです。「bossaction->Action(sp , bs);」がボスを動かすメソッドです。

コード:

class BossAction {
protected:
	int t;
	int t_limit;
	void LimitCnt();
public:
	BossAction() {t = 0; };
	virtual void Action(SpriteData &sp , BossData &bs) = 0;
	int ReturnTimeLimit() {return  t_limit; };
};

class BossActionIn : public BossAction {
public:
	BossActionIn():BossAction() { t_limit = 30; };
	virtual void Action(SpriteData& sp, BossData& bs)override;
};

class BossActionTurn : public BossAction {
public:
	BossActionTurn() :BossAction() {};
	virtual void Action(SpriteData& sp, BossData& bs)override;
};

class BossActionWait : public BossAction {
public:
	BossActionWait() :BossAction() {	};
	virtual void Action(SpriteData& sp, BossData& bs)override;
};


class BossAction01 : public BossAction{
public:
	BossAction01() :BossAction() { t_limit = 30;};
	virtual void Action(SpriteData& sp, BossData& bs)override;
};

class BossAction02 : public BossAction {
public:
	BossAction02() :BossAction() {t_limit = 60;};
	virtual void Action(SpriteData& sp, BossData& bs)override;
};

class BossAction03 : public BossAction {
public:
	BossAction03() :BossAction() {t_limit = 30;};
	virtual void Action(SpriteData& sp, BossData& bs)override;
};

class BossAction04 : public BossAction {
public:
	BossAction04() :BossAction() {t_limit = 120; };
	virtual void Action(SpriteData& sp, BossData& bs)override;
};

//以下は本来はBossクラスのupdate()メソッドに内に書かれているです部分です。
	switch (bs.act_id) {
	case -2:	
		if (typeid(bossaction) != typeid(BossActionWait))bossaction.reset(new BossActionWait);
		break;
	case -1:			
		if (typeid(bossaction) != typeid(BossActionTurn))bossaction.reset(new BossActionTurn);
		break;
	case 0:
		if (typeid(bossaction) != typeid(BossActionIn))bossaction.reset(new BossActionIn);
		break;
	case 1:	
		if (typeid(bossaction) != typeid(BossAction01))bossaction.reset(new BossAction01);
		break;
	case 2:
		if (typeid(bossaction) != typeid(BossAction02))bossaction.reset(new BossAction02);
		break;
	case 3:
		if (typeid(bossaction) != typeid(BossAction03))bossaction.reset(new BossAction03);
		break;
	case 4:
		if (typeid(bossaction) != typeid(BossAction04))bossaction.reset(new BossAction04);
		break;
	}
	bossaction->Action(sp , bs);

アバター
spaaaark・∀・
記事: 66
登録日時: 10年前
住所: 埼玉
連絡を取る:

Re: ループ内でのオブジェクトの動的確保について

#2

投稿記事 by spaaaark・∀・ » 3年前

検証してみましたが、typeidが一致するのはポインタの実体を入れたときだけのようです。
なのでポインタの実体を参照するようにするとうまく行くと思います。
(ただし、ぬるぽにはご注意ください。)

検証コード:
https://ideone.com/4f0Eht
クリエイティブな生活で刺激的な毎日を!

あげだま

Re: ループ内でのオブジェクトの動的確保について

#3

投稿記事 by あげだま » 3年前

spaaaark・∀・さん
返信ありがとうございます。お陰様でtypeidの使い方が間違っていたことに気づくことができました。
しかし該当箇所を改善して実行してみると今度は「Debug Error! Program: ~~.exe abort() has been called (Press Retry to debug the application)」と出てしまいます。試しに似たような小コードを書いてみたのですが、やはり同じようなエラーが出るようです。原因を教えていただけると幸いです。

コード:

#include <iostream>
#include <memory>
#include <typeinfo>

using namespace std;

class Car {
public:
	virtual void Display() = 0;
};

class RacingCar :public Car {
public:
	void Display() override{
		cout << "レーシングカーです"<<endl;
	}
};

class PassengerCar :public Car {
public:
	void Display() override{
		cout << "乗用車です"<<endl;
	}
};

int main() {
	int id = 1;
	unique_ptr<Car>car;	
	if (id == 1 && typeid(*car) != typeid(RacingCar))car.reset(new RacingCar);
	if (id == 2 && typeid(*car) != typeid(PassengerCar))car.reset(new PassengerCar);
	car.reset(new PassengerCar);
	return 0;
}

あげだま

Re: ループ内でのオブジェクトの動的確保について

#4

投稿記事 by あげだま » 3年前

31行目のcar.reset(new PassengerCar);はテスト用です。
消し忘れてました。

アバター
spaaaark・∀・
記事: 66
登録日時: 10年前
住所: 埼玉
連絡を取る:

Re: ループ内でのオブジェクトの動的確保について

#5

投稿記事 by spaaaark・∀・ » 3年前

このコードは、気を付けてくださいと言ったぬるぽを出しています((
if文の比較の際car変数が実体を指さないために、このコードは実行時エラーとなります。
対策は、例えば消し忘れたコードをif文の手前に持ってくるとコードは動作します。
(if文での比較前にcar変数にインスタンスを生成することがポイントです。)

恐らく現物の実装は常時実体があるわけではないと思うので、
宣言の際にcar(nullptr)と、スマートポインタをnullptrで初期化したうえで、
nullptrをif文でチェックしてから紹介した比較を行う必要があります。
なおこのとき、nullptrからインスタンスを作成する条件文は別途必要です。
クリエイティブな生活で刺激的な毎日を!

あげだま

Re: ループ内でのオブジェクトの動的確保について

#6

投稿記事 by あげだま » 3年前

どうもありがとうございました。
お陰様で望む通りに動いてくれました。

返信

“C言語何でも質問掲示板” へ戻る