如何从包含类名的字符串实例化对象?
在给定的代码中,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中文网其他相关文章!