c++ - 根据 C++ 中的字符串值创建类对象实例的好方法?
问题描述
请参阅问题的代码片段:
class Base;
typedef Base* BasePtr;
template<typename D>
BasePtr CreateDerivedClass() {
return new D();
}
class D1 : public Base {
....
};
class D2 : public Base {
....
}
void main() {
std::string derived_name = {"D1", "D2"};
std::vector<BasePtr> derived_vec;
for (auto& name : derived_name) {
// QUESTION: Other than factory design pattern, how can I pass the derived
// class typename which is the value of string "name" to CreateDerivedClass<name> ?
derived_vec.push_back(CreateDerivedClass<name>());
}
}
注意:在这里,我不想使用在定义期间需要派生类寄存器本身的工厂设计模式。
解决方案
模板参数值必须在编译时已知。没有简单的方法可以在运行时直接将字符串转换为用于模板参数的类型。您必须在运行时比较字符串值来决定调用哪个特化。CreateDerivedClass
例如,处理此问题的最简单方法是使用 astd::map
其中的元素保存指向您希望能够调用的专用函数的指针,例如:
using createFuncType = BasePtr (*)();
std::map<std::string, createFuncType> createFuncs;
createFuncs["D1"] = &CreateDerivedClass<D1>;
createFuncs["D2"] = &CreateDerivedClass<D2>;
...
然后你可以这样做:
std::string derived_names[] = {"D1", "D2"};
std::vector<BasePtr> derived_vec;
for (auto& name : derived_names) {
derived_vec.push_back(createFuncs[name]());
}
在这种情况下确实没有其他选择。
话虽如此,您应该使用std::unique_ptr<Base>
而不是原始Base*
指针,例如:
#include <map>
#include <vector>
#include <string>
#include <memory>
class Base {
public:
virtual ~Base() = default;
};
using BasePtr = std::unique_ptr<Base>;
using createFuncType = BasePtr (*)();
template<typename D>
BasePtr CreateDerivedClass() {
return std::make_unique<D>();
}
class D1 : public Base {
...
};
class D2 : public Base {
...
}
...
int main() {
std::map<std::string, createFuncType> createFuncs;
createFuncs["D1"] = &CreateDerivedClass<D1>;
createFuncs["D2"] = &CreateDerivedClass<D2>;
...
std::string derived_names = {"D1", "D2", ...};
std::vector<BasePtr> derived_vec;
for (auto& name : derived_names) {
derived_vec.push_back(createFuncs[name]());
}
...
return 0;
}
推荐阅读
- haskell - Haskell 排序的随机列表是无限的
- animation - Flutter 设置开始动画值
- python - 突出显示图片的一部分并选择它
- java - Java ProcessBuilder 在线程中不起作用
- uibezierpath - 从 UIBezierpath 中删除部分
- ios - 不使用用户的当前位置,但苹果请求“应用程序的 Info.plist 文件应包含 NSLocationWhenInUseUsageDescription 键”
- javascript - componentDidCatch + window.addEventListener('error', cb) 未按预期运行
- ios - 解雇了 Imagepickercontroller 和当前模态呈现的视图控制器(弹出控制器)
- c# - 未呈现活动路由自定义 TagHelper
- python - 如何获得一个范围的平均值?