クラス名を含む文字列からオブジェクトをインスタンス化する方法?
指定されたコードで、BaseFactory クラスはさまざまな派生クラスのオブジェクトを作成しますクラス名を表す文字列に基づきます。ただし、ファクトリでは、考えられる派生クラスごとに if ステートメントを手動で追加する必要があります。 C# のリフレクション機能と同様、この冗長なアプローチに代わるものはないのかと疑問に思う人もいるかもしれません。
残念ながら、自動化されたメカニズムはありません
残念ながら、C にはメカニズムがありません。実行時に指定されたタイプのオブジェクトを自動作成する場合。ただし、マッピングを自分で行うことも可能です。
型マッピング
クラス名ごとに、オブジェクトを作成する関数を格納するマップを作成できます。そのクラスの:
template<typename T> Base * createInstance() { return new T; } typedef std::map<std::string, Base*(*)()> map_type; map_type map; map["DerivedA"] = &createInstance<DerivedA>; map["DerivedB"] = &createInstance<DerivedB>;
その後、オブジェクトもインスタンス化できますhelp:
return map[some_string]();
型の登録
別の解決策は、型自体を登録できるようにすることです:
// w base.hpp: template<typename T> Base * createT() { return new T; } struct BaseFactory { typedef std::map<std::string, Base*(*)()> map_type; static Base * createInstance(std::string const& s) { map_type::iterator it = getMap()->find(s); if(it == getMap()->end()) return 0; return it->second(); } protected: static map_type * getMap() { // nigdy nie usuwane (istnieje do zakończenia programu) // ponieważ nie możemy zagwarantować poprawnej kolejności usuwania if(!map) { map = new map_type; } return map; } private: static map_type * map; }; template<typename T> struct DerivedRegister : BaseFactory { DerivedRegister(std::string const& s) { getMap()->insert(std::make_pair(s, &createT<T>)); } }; // w derivedb.hpp class DerivedB { ...; private: static DerivedRegister<DerivedB> reg; }; // w derivedb.cpp: DerivedRegister<DerivedB> DerivedB::reg("DerivedB");
マクロを定義することもできます型登録の場合:
#define REGISTER_DEC_TYPE(NAME) \ static DerivedRegister<NAME> reg #define REGISTER_DEF_TYPE(NAME) \ DerivedRegister<NAME> NAME::reg(#NAME)
共通の基本クラスを共有しない型の場合は、バリアントを使用できます。関数の戻り値の型として boost::variant:
typedef boost::variant<Foo, Bar, Baz> variant_type; template<typename T> variant_type createInstance() { return variant_type(T()); } typedef std::map<std::string, variant_type (*)()> map_type;
以上がクラス名を含む文字列から C オブジェクトを作成するにはどうすればよいですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。