将类类型中的类实例化为 std::map 值的C++
Instantiate class in C++ from class type as std::map value
我需要将以下Java概念移植到C++:
保存对象 ID 键和类类型值的哈希映射:
Map<String, Class> _objectsBank = new HashMap<>();
在 init 方法的某个地方,我像这样填充银行:
_objectsBank .put("CLASS_ID_1", MyClass1.class);
_objectsBank .put("CLASS_ID_2", MyClass2.class);
....
然后,稍后,我构造了一个按需求保存在该银行中的类的实例。有点"懒惰"的初始化:
private MyClass initNewProg(String name) {
MyClass instance;
try {
Class cl = _objectsBank.get(name);
java.lang.reflect.Constructor co = cl.getConstructor(String.class);
instance= (MyClass) co.newInstance(name);
return instance;
} catch (NoSuchMethodException | SecurityException | InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e)
{
e.printStackTrace();
return null;
}
}
我将如何在C++中做到这一点?如何将类类型设置为 std::map 值,以便以后可以查询它以从中构造适当的实例?Boost 库中有这样的东西吗?
您可以使用函数指针。由于不能将函数指针指向构造函数,因此必须使用工厂函数:
template <class Derived>
Base* create()
{
return new Derived;
}
然后,可以将函数指针保存到映射中工厂函数的模板实例,以构造派生类:
int main()
{
std::map<std::string, Base*(*)()> classMap;
classMap["Derived1"] = &create<Derived1>;
classMap["Derived2"] = &create<Derived2>;
delete classMap["Derived1"]();
delete classMap["Derived2"]();
}
在 Ideone 上看到它
看看有没有办法从保存类名的字符串中实例化对象? 以及使用工厂模式按名称实例化类,这些模式描述了问题和多种方法以及每种方法的优缺点。这些示例涵盖了类的构造器的注册,这解决了您在 T 的解决方案中提到的多个 if 语句的问题@Karthik。
一种选择是,您可以存储表示实例的字符串,而不是类名,然后使用工厂方法返回正确的实例。但这将更笨拙,因为您需要通过执行以下操作来手动模拟反射过程。
MyClass* initNewProg(string name) {
if(name == "derived1")
return new Derived1();
else if(name == "derived2")
....
}
另一种替代方法是使用单独的工厂方法和函数指针。
typedef MyClass* (*MyFactoryFunc)();
map<string,MyFactoryFunc> myMap;
MyClass* createDerived1(){return new Derived1();}
...
MyClass* initNewProg(string name) {
return myMap[name]();
}
如果使用Qt并将对象转换为QObjects是一种选择,那么它可以通过Qt元对象系统来实现。研究它的实用起点是QObject::metaObject()
和QMetaObject::newInstance()
方法文档。
这也说明了一点,在C++或多或少的情况下获得这样的功能需要额外的预处理步骤,例如Qt的moc
,它会使用额外的方法和数据来创建额外的.cpp文件来支持这一点。
一个更轻量级的选择可能是开发你自己的简单预处理器,例如,它读取.cpp文件中的一些特殊注释符号,并可能生成代码来创建映射,将对象类型映射到实例化对象的函数,或者其他东西。我不确定你能哄骗C++模板系统为你完成大部分工作。
- 如何导出包含具有"std::unique_ptr"值的"std::map"属性的
- std::map<struct,struct>::find 找不到匹配项,但是如果我循环通过 begin() 到 end(),我在那里看到匹配项
- 使用一个考虑到std::map中键值的滚动或换行的键
- 为什么 const std::p air<K,V>& 在 std::map 上基于范围的 for 循环不起作用?
- 允许从 std::map 的密钥窃取资源?
- 有没有办法对std::unordered_set、std::unrdered_map、std::set、std::map
- 将重物插入std::map
- 使用通用值初始化 std::map,不重复
- 仅包含可移动 std::map 的类的移动构造函数不起作用
- C++:当所有条目都保证是唯一时,替代 std::map
- 使用模板化的键类型定义 std::map,该键类型基于作为参数接收的函数
- 如果 KEY 是 std::list 或 std::vector 而不是值,那么 std::map 的默认行为是什么?
- 使用字符数组作为 Map 中的键
- C++如何创建 std::map
- C++ equivalent to Java Map getOrDefault?
- 从其他容器中移动构造"std::map"
- 如何使用 uint64_t 键类型从 std::map<int, std::string> 返回值?
- 将 std::map::emplace 与返回 shared_ptr 的函数一起使用是否正确?
- C++中 std::map 的运行时复杂度是多少?
- 为什么在 std::map 上移动无法将元素从一个映射移动到另一个映射