从类名字符串实例化对象
在 C 中,如果没有显式映射,则无法从包含类名的字符串实例化对象。此限制源于 C 的静态特性,其中类型必须在编译时已知。
选项 1:使用模板手动映射
您可以创建模板函数对于要实例化的每个类以及将类名称链接到相应模板函数的映射。例如:
template<typename T> Base* createInstance() { return new T; } map_type map; map["DerivedA"] = &createInstance<DerivedA>; map["DerivedB"] = &createInstance<DerivedB>;
要实例化对象,请使用:
return map[some_string]();
选项 2:运行时类型注册
您可以拥有类使用静态机制注册自身,然后动态检索实例。这涉及使用单例映射来存储类名到函数的映射。下面是一个示例:
struct BaseFactory { static Base * createInstance(std::string const& s) { auto it = getMap()->find(s); return it != getMap()->end() ? it->second() : nullptr; } static std::map<std::string, std::function<Base*()>> * getMap() { if (!map) { map = new std::map<std::string, std::function<Base*()>>; } return map; } private: static std::map<std::string, std::function<Base*()>> * map; }; template<typename T> struct DerivedRegister : BaseFactory { DerivedRegister(std::string const& s) { getMap()->insert({s, &createInstance<T>}); } }; class DerivedB { private: static DerivedRegister<DerivedB> reg("DerivedB"); };
此方法允许在运行时自动注册类。
选项 3:Boost Variant
如果您有没有共同基类的不相关类,您可以使用 Boost 变体库:
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 缺乏从类名字符串实例化对象的内置机制。但是,使用模板、运行时注册或 Boost 变体库,您可以实现类似的功能。
以上是如何从类名字符串实例化 C 对象?的详细内容。更多信息请关注PHP中文网其他相关文章!