在c ++中用string创建类以避免大的switch语句?

时间:2013-09-06 20:53:12

标签: c++ gcc

我正在重构C ++应用程序以更好地利用多态性。我有一个大的工厂方法,基于Enum实例化适当的对象。有没有一种方法可以让一个查找表从Enum的值映射到我可以用来创建正确对象的类?

3 个答案:

答案 0 :(得分:4)

是的,请使用地图:

struct Base { virtual ~Base(); };

struct Factory
{
    enum Types { ThingA, WidgetB, GadgetC };

    typedef Base * (*MakerFunction)();

    static std::map<Types, MakerFunction> makers;

    static std::unique_ptr<Base> create(Types t)
    {
        return { makers[t]() };
    }
};

现在,对于从Base派生的每个对象,您只需在地图Factory::makers中插入合适的创建函数。

示例:

struct Thing : Base
{
    static Base * create() { return new Thing; }
};

// somewhere

Factory::makers[Factory::ThingA] = &Thing::create;

(就个人而言,我可能在所有接口中都使用unique_ptr,并且可能有某种自我注册机制,辅助类在构造函数中进行注册。你也想要添加枚举值实际在地图中的检查。您也可以使用这种方法进行字符串键选择。)

答案 1 :(得分:1)

您不能拥有从枚举到类的映射,但您可以拥有一个到工厂函数。像

这样的东西
typedef BaseClass* (*Maker_t)();

template <typename T>
BaseClass* Maker() { return new T(); }

std::map<MyEnum, Maker_t> makers = {{CLASS_A, Maker<ClassA>}, ...};

BaseClass* b = makers[enumValue]();

答案 2 :(得分:1)

不确定。给自己写一个模板工厂函数,例如:

enum EnumType {
     Derived1,
     Derived2,
     ...
};

template <class T>
MyBase* CreateSomething() {
    return new T();
}

然后声明一个这样的查找表:

typedef MyBase*(*factory_t)();
factory_t factories[] = {
     &CreateSomething<Derived1>,
     &CreateSomething<Derived2>,
     ...
}

并像这样调用:

EnumType my_val = ...;
MyBase* b = factories[my_val]();

我建议使用unique_ptr而不是原始指针来保证安全性,我只使用上面的原始指针来保持示例简单。对于std :: array或std :: vector而不是数组也一样。

如果您的枚举值是备用的,那么std :: map可能更合适,但是使用正常的枚举(连续,从零开始),这是不必要的开销。

相关问题