Home >Backend Development >C++ >How to Create C Objects from a String Containing Their Class Name?
How to Instantiate Objects from a String Containing Their Class Name?
In the given code, a BaseFactory class creates objects of different Derived classes based on a string representing their class name. However, the factory requires manual addition of if statements for each possible Derived class. One may wonder if there's an alternative to this verbose approach, similar to C#'s Reflection feature.
unfortunately there is no automated mechanism
Unfortunately, C does not have a mechanism for automatic creation objects of types specified at runtime. However, it is possible to do the mapping yourself:
Type mapping
You can create a map that stores, for each class name, a function that creates an object of that class:
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>;
Then you can instantiate the objects too help:
return map[some_string]();
Type registration
An alternative solution is to allow types to register themselves:
// 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");
You can also define macros for type registration :
#define REGISTER_DEC_TYPE(NAME) \ static DerivedRegister<NAME> reg #define REGISTER_DEF_TYPE(NAME) \ DerivedRegister<NAME> NAME::reg(#NAME)
For types that do not share a common base class, you can use the variant boost::variant as the return type of function:
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;
The above is the detailed content of How to Create C Objects from a String Containing Their Class Name?. For more information, please follow other related articles on the PHP Chinese website!