我正在构建一个可以通过添加新类来扩展的 c++ 框架
我想找到一种方法来简化新类的扩展。
我当前的代码如下:
class Base {
public:
virtual void doxxx() {...}
};
class X: public Base {
public:
static bool isMe(int i) { return i == 1; }
};
class Y: public Base {
public:
static bool isMe(int i) { return i == 2; }
};
class Factory {
public:
static std::unique_ptr<Base> getObject(int i) {
if (X::isMe(i)) return std::make_unique<X>();
if (Y::isMe(i)) return std::make_unique<Y>();
throw ....
}
};
还必须为每个新类添加一个新的 if 语句。
现在我想找到一种方法来重写我的工厂类(使用元编程),可以通过调用 add 方法来添加新类 工厂类看起来像下面的伪代码:
class Factory
{
public:
static std::unique_ptr<Base> getObject(int i) {
for X in classNames:
if (X::isMe(i)) return std::make_unique<X>();
throw ....
}
static void add() {...}
static classNames[];...
};
Factory::add(X);
Factory::add(Y);
. .
这样的事情可能吗? 非常感谢
最佳答案
您可能会执行以下操作:
template <typename ... Ts>
class Factory {
public:
static std::unique_ptr<Base> createObject(int i) {
if (i < sizeof...(Ts)) {
static const std::function<std::unique_ptr<Base>()> fs[] = {
[](){ return std::make_unique<Ts>();}...
};
return fs[i]();
}
throw std::runtime_error("Invalid arg");
}
};
用法是:
using MyFactory = Factory<X, Y /*, ...*/>;
auto x = MyFactory::createObject(0);
auto y = MyFactory::createObject(1);
如果你想要运行时注册,你可以这样做:
class Factory {
public:
static std::unique_ptr<Base> createObject(int i) {
auto it = builders.find(i);
if (it == builders.end()) {
throw std::runtime_error("Invalid arg");
}
return it->second();
}
template <typename T>
void Register()
{
builders.emplace(T::Id, [](){ return std::make_unique<T>();});
}
private:
std::map<int, std::function<std::unique_ptr<Base>()>> builders;
};
用法是:
class X: public Base {
public:
static constexpr int id = 1;
};
class Y: public Base {
public:
static constexpr int id = 2;
};
和
Factory factory;
factory.register<X>();
factory.register<Y>();
auto x = factory.createObject(1);
auto y = factory.createObject(Y::id);
关于C++类名数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48926376/