从字符串到类型(C++)的最佳方法是什么
Whats best way to go from a String to Type (C++)
我希望能够将中的类型指定为字符串,并在C++中创建该类型。我知道C++不直接支持这一点,但最好的方法是什么?
我目前有一个包含信息的xml,但我想将其扩展到包含组件。
<entity>
<component>ComponentA</component>
<component>ComponentB</component>
</entity>
我有一个通用工厂,它接收这些xml并构建实体。我希望能够避免if("componentA") { new ComponentA; }
,而选择更通用的内容。主要是因为组件将由客户定义,而工厂不是。
我原以为组件可以在工厂注册并存储地图,但这需要持有我想避免的所有组件的副本。
我的跨平台解决方案会更好。
AFAIK,至少在通用C++中,没有只使用字符串创建类的隐式方法。然而,我过去使用过另一种机制。
首先,您定义了组件的概念:
class Component /* or IComponent if you're feeling adventurous - we may not have interfaces in C++, but dammit we like 'em! */
{
protected:
Component() { };
public:
virtual ~Component() = 0 { };
}; // eo class Component
还有某种创造者的概念:
class ComponentCreator
{
protected:
Component() { };
public:
virtual ~ComponentCreator() = 0 { };
virtual Component* create() const = 0; // Might want to use smart-pointers here - this is for illustrative purposes only.
}; // eo class ComponentCreator
好吧,我们有了基本的东西,现在我们需要一个可以让这些创作者注册的工厂:
class Factory
{
private:
std::map<std::string, ComponentCreator*> _creators;
public:
Factory() : _creators(new std::map<std::string, ComponentCreator*>();
{
};
~Factory()
{
// cleanup of _creators ommited.
};
// call to register a creator
void register(const std::string& name, ComponentCreator* creator)
{
// normally you'd put checks to see if it exists etc.
_creators[name] = creator;
}; // eo register
// call to create an instance
Component* create(const std::string& name)
{
std::map<std::string, ComponentCreator*>::const_iterator cit(_creators.find(name));
if(cit != _creators.end())
return cit->create();
else
return NULL; // or nullptr
}; // eo create
}; // eo class Factory
如此声明你的类(我只做一个):
class ComponentA : public Component { /* implementation */ };
别忘了创造者:
class ComponentCreatorForA : public ComponentCreator
{
public:
virtual Component* create() const { return new ComponentA(); };
}; // eo class ComponentCreatorForA
在程序初始化期间,您注册组件创建者:
factory.register("componentA", new ComponentCreatorForA());
factory.register("componentB", new ComponentCreatorForB());
稍后,我们可以按名称创建组件:
Component* component = factory.create("componentA");
备注:
这种方法假定组件在编译时是已知的。如果没有的话,可以引入插件体系结构,这样额外的DLL就可以在启动时通过工厂注册它们的组件,这样你就可以使它具有可扩展性,而不必重新部署所有内容。
在现实世界中,我们会使用一些这样的智能指针,并去掉typedef很多这样的东西,以使打字更容易!
您必须存储有关组件类的元信息。一个可能的解决方案可能使用模板:
// the component interface
class BaseComponent {...}
// structure containing meta-information
template<typename ComponentType>
struct tComponentMeta {
typedef ComponentType type;
std::string componentTypeName;
tComponentMeta() : componentTypeName("no valid component type") {}
}
// providing run time type information
// (optional, but i like it if the component know about their type
template<typename ComponentType>
class TComponent : public BaseComponent
{
tComponentMeta<ComponentType> metaInfo;
TComponent(const std::string& uniqueTypeName) {...};
}
class ConcreteComponent : public TComponent<ConcreteComponent>
{
...
}
现在,客户端必须为ConcreteComponent类型定义专门的tComponentMeta。这可以通过在ConcreteComponent的类声明后添加以下代码来实现:
template <>
struct tComponentMeta {
typedef ConcreteComponent type
tComponentMeta() : componentTypeName("ConcreteComponent") {}
}
因此,如果您的客户端为组件定义了模板专用化,您可以为它们提供一个通用工厂,该工厂具有以下类型的模板方法,该方法也必须由设计组件的客户端调用:
...
template<typename ComponentType>
registerComponentType() {
tComponentMeta<ComponentType> metaInfo;
nameToMetaMap.put(metaInfo.name, metaInfo)
}
使用这些构建块,您可以通过强制客户端提供其组件的tComponentMeta专用化并在通用工厂注册组件类型来以通用方式生成组件。
这段代码还没有经过我自己的测试,所以你可以假设有一些语法错误,但我希望这个想法是清楚的。
由于模板的性质,该方法也应适用于使用DLL的插件架构。
- 在C#中处理C++指针而不使用unsafe的最佳方法
- 在C++中,将大的无符号浮点数四舍五入为整数的最佳方法是什么
- 实现无开销push_back的最佳方法是什么
- 在C++中向零方向近似的最佳方法
- 使用不同的CRT将新的C++代码与旧的(二进制)组件隔离开来的最佳方法是什么
- 检测win32服务创建和删除的最佳方法
- 在C++中样板"冷/never_inline"错误处理技术的最佳方法是什么?
- 在 c++ 中对类中的 c 字符串动态数组进行排序的最佳方法是什么?
- 将线程中的数据存储到全局容器的最佳方法?
- 将一系列整数放入类的最佳方法是什么?
- 在派生类中使用基类的私有成员变量的最佳方法
- 在 C++ 中将非指定类型作为参数传递的最佳方法?
- Qt - QVector 和模型视图 - 从列表视图获取自定义类的最佳方法是什么?
- 使用 Git 处理 C++ Visual Studio 2019 解决方案的外部依赖项源代码管理的最佳方法是什么?
- 比较两个节点坐标的最佳方法是什么?
- 在nodejs中使用本机代码的最佳方法是什么?
- 将 pybind11 绑定标记为已弃用的最佳方法
- C++:将向量传递到构造函数以创建成员变量的最佳方法?
- C++中变量混叠的最佳方法
- 读取大文件(>2GB)(文本文件包含以太网数据)并通过不同参数随机访问数据的最佳方法是什么?