您实际上可以使用一些模板技巧来做到这一点:
#include <map>
template <typename Enum, typename Base>
class EnumFactory {
public:
static Base* create(Enum e) {
typename std::map<Enum,EnumFactory<Enum,Base>*>::const_iterator const it = lookup().find(e);
if (it == lookup().end())
return 0;
return it->second->create();
}
protected:
static std::map<Enum,EnumFactory<Enum,Base>*>& lookup() {
static std::map<Enum,EnumFactory<Enum,Base>*> l;
return l;
}
private:
virtual Base* create() = 0;
};
template <typename Enum, typename Base, typename Der>
class EnumFactoryImpl : public EnumFactory<Enum,Base> {
public:
EnumFactoryImpl(Enum key)
: position(this->lookup().insert(std::make_pair<Enum,EnumFactory<Enum,Base>*>(key,this)).first) {
}
~EnumFactoryImpl() {
this->lookup().erase(position);
}
private:
virtual Base* create() {
return new Der();
}
typename std::map<Enum,EnumFactory<Enum,Base>*>::iterator position;
};
这允许您从给定创建一个新的派生对象enum
,通过说
// will create a new `FancyType` object if `value` evaluates to `FANCY_TYPE_VALUE` at runtime
EnumFactory<MyEnum,MyBase>::create(value)
但是,您必须有一些 EnumFactoryImpl 对象,这些对象在某些函数或命名空间中可能是静态的。
namespace {
EnumFactoryImpl<MyEnum,MyBase,Derived1> const fi1(ENUM_VALUE_1);
EnumFactoryImpl<MyEnum,MyBase,Derived2> const fi2(ENUM_VALUE_2);
EnumFactoryImpl<MyEnum,MyBase,Derived3> const fi3(ENUM_VALUE_3);
EnumFactoryImpl<MyEnum,MyBase,FancyType> const fi1(FANCY_TYPE_VALUE); // your example
}
这些行是源代码将enum
值映射到派生类型的单点。因此,您将所有内容都放在同一个位置,并且没有冗余(这消除了在添加新派生类型时忘记在某些地方更改它的问题)。