Wie instanziiere ich Objekte aus einer Zeichenfolge, die ihren Klassennamen enthält?
Im angegebenen Code erstellt eine BaseFactory-Klasse Objekte verschiedener abgeleiteter Klassen basierend auf einer Zeichenfolge, die ihren Klassennamen darstellt. Die Factory erfordert jedoch das manuelle Hinzufügen von if-Anweisungen für jede mögliche abgeleitete Klasse. Man könnte sich fragen, ob es eine Alternative zu diesem ausführlichen Ansatz gibt, ähnlich der Reflection-Funktion von C#.
Leider gibt es keinen automatisierten Mechanismus
Leider verfügt C nicht über einen Mechanismus für die automatische Erstellung von Objekten der zur Laufzeit angegebenen Typen. Es ist jedoch möglich, die Zuordnung selbst vorzunehmen:
Typzuordnung
Sie können eine Zuordnung erstellen, die für jeden Klassennamen eine Funktion speichert, die ein Objekt erstellt dieser Klasse:
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>;
Dann können Sie die Objekte auch instanziieren Hilfe:
return map[some_string]();
Typregistrierung
Eine alternative Lösung besteht darin, Typen zu erlauben, sich selbst zu registrieren:
// 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");
Sie können auch Makros definieren zur Typregistrierung:
#define REGISTER_DEC_TYPE(NAME) \ static DerivedRegister<NAME> reg #define REGISTER_DEF_TYPE(NAME) \ DerivedRegister<NAME> NAME::reg(#NAME)
Für Typen, die keine gemeinsame Basisklasse haben, können Sie die Variante verwenden boost::variant als Rückgabetyp der Funktion:
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;
Das obige ist der detaillierte Inhalt vonWie erstelle ich C-Objekte aus einer Zeichenfolge, die ihren Klassennamen enthält?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!