Comment instancier des objets à partir d'une chaîne contenant leur nom de classe ?
Dans le code donné, une classe BaseFactory crée des objets de différentes classes dérivées basé sur une chaîne représentant leur nom de classe. Cependant, l'usine exige l'ajout manuel d'instructions if pour chaque classe dérivée possible. On peut se demander s'il existe une alternative à cette approche verbeuse, similaire à la fonctionnalité Reflection de C#.
malheureusement il n'y a pas de mécanisme automatisé
Malheureusement, C n'a pas de mécanisme pour les objets de création automatique des types spécifiés au moment de l'exécution. Cependant, il est possible de faire le mappage vous-même :
Mappage de types
Vous pouvez créer une carte qui stocke, pour chaque nom de classe, une fonction qui crée un objet de cette classe :
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>;
Ensuite, vous pouvez également instancier les objets help:
return map[some_string]();
Enregistrement des types
Une solution alternative consiste à permettre aux types de s'enregistrer eux-mêmes :
// 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");
Vous pouvez également définir des macros pour l'enregistrement de type :
#define REGISTER_DEC_TYPE(NAME) \ static DerivedRegister<NAME> reg #define REGISTER_DEF_TYPE(NAME) \ DerivedRegister<NAME> NAME::reg(#NAME)
Pour les types qui ne partagent pas une classe de base commune, vous pouvez utiliser la variante boost::variant comme type de retour de fonction:
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;
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!