[C++]クラス名の文字列からそのクラスのインスタンスを生成する方法

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

[C++]クラス名の文字列からそのクラスのインスタンスを生成する方法

#1

投稿記事 by natsu » 5年前

C++のクラスについての質問です。

抽象クラスBASEを継承したクラスがCLASS1~CLASS10まであるとします。
同じクラスを継承したクラスのインスタンスをまとめて制御したいため、基底クラスのvectorを作って管理しています。

std::vector<BASE*> classes;

classes.push_back(new CLASS1());
classes.push_back(new CLASS2());
...
classes.push_back(new CLASS10());

たいした記述量ではないのですが、新しいクラスを定義した時に追加する処理が地味に面倒に感じます。
なので上記のようなプログラムをfor文で書けるようになればとても都合がいいのです。
具体的には、テキストファイルにクラス名のリストを書いておき、それを読み込みながらクラスのインスタンスを生成したいです。
C#ではできなくはないみたいなのですが、C++でこれを実現するのは無理でしょうか?

アバター
tk-xleader
記事: 153
登録日時: 9年前
連絡を取る:

Re: [C++]クラス名の文字列からそのクラスのインスタンスを生成する方法

#2

投稿記事 by tk-xleader » 5年前

 C++には実行時に生成する型を決定してオブジェクトを作成する機構は言語には直接には組み込まれていませんので、一工夫が必要となります。C++でそれを実現しようと思えば、ちょっと面倒ですがstd::mapを応用すれば何とかなりそうです。

コード:

// サンプルなので使用していないですが、newしたオブジェクトはstd::shared_ptrなどのスマートポインタで管理したほうが安全でしょう。

class IObjectBuilder{
public:
	virtual IObject* Create() = 0;
};

template<typename T>
class ObjectBuilder : public IObjectBuilder{
public:
	virtual T* Create(){return new T;}
};

#define REGISTER_ARGS(TYPE) #TYPE,new ObjectBuilder<TYPE>
class BuilderFromString{
	std::map<std::string,IObjectBuilder*> builders;
public:
	void Register(const string& ty_name,IObjectBuilder* builder){
		builders.insert(std::make_pair(ty_name,builder));
	}
	IObject* Create(const std::string& ty_name){
		std::map<std::string,IObjectBuilder*>::iterator itr = builders.find(ty_name);
		if(itr == builders.end())return 0;
		return (*itr).second->Create();
	}
};

// 使用例
BuilderFromString builderfromstring;
builderfromstring.Register(REGISTER_ARGS(CLASS1));
builderfromstring.Register(REGISTER_ARGS(CLASS2));
builderfromstring.Register(REGISTER_ARGS(CLASS3));
builderfromstring.Register(REGISTER_ARGS(CLASS4));
// ……必要なクラスを登録していく。

IObject* object1 = builderfromstring.Create("CLASS1");
IObject* object2 = builderfromstring.Create("CLASS2");
このまま使うには色々と問題があるコードですが、一応考え方のサンプルです。

閉鎖

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