由于缺乏反射,在C++中是一个不可避免的大开关块

ROT*_*OGG 6 c++ oop factory

假设我有一个类的层次结构:

class Shape {
};

class Circle : public Shape {
}

class Square : public Shape {
}

... hundreds of other shapes continue on...
Run Code Online (Sandbox Code Playgroud)

当给定形状类的名称作为字符串时,我需要实例化该类的对象.

在java中,我可以做这样的事情(伪代码!)

Shape createShape(String name) {
    return new Class.forName(name);
}
Run Code Online (Sandbox Code Playgroud)

但是在C++中,我必须这样做:(伪代码!)

Shape * createShape(const string &name) {
    if (name.compare("Circle") == 0) {  
        return new Circle();
    }
    else if (name.compare("Square") == 0) {
        return new Square();
    }
    else if ... //hundreds of else if continues, one for each shape
}
Run Code Online (Sandbox Code Playgroud)

有没有更好的方法在C++中处理这样的情况?

Ada*_*eld 6

使用工厂模式是可以避免的,但是你仍然需要一堆样板代码来开始.例如:

// Class factory functions -- these could also be inlined into their respective
// class definitions using a macro
Shape *createCircle() { return new Circle(); }
Shape *createSquare() { return new Square(); }
// etc.

// Create a map from type name to factory
typedef std::map<std::string, Shape *(*)()> ShapeFactoryMap;
ShapeFactoryMap factoryMap;
factoryMap["Circle"] = &createCircle;
factoryMap["Square"] = &createSquare;
// etc.
Run Code Online (Sandbox Code Playgroud)

然后,当您想要实例化对象时,您可以这样做:

ShapeFactoryMap::iterator factory = factoryMap.find("Circle");
if (factory != factoryMap.end())
{
    Shape *circle = factory->second();  // Creates a Circle instance
    ...
}
else
{
    // Handle error
}
Run Code Online (Sandbox Code Playgroud)

这是否比仅进行一系列if/else...字符串比较更好还不清楚,因为它取决于你正在做什么来做这件事.

  • `map ["circle"] = [] {return new Circle(); ``会更好,只是为了不使用独立函数来混淆命名空间. (3认同)
  • 也许[`std :: unordered_map`](http://en.cppreference.com/w/cpp/container/unordered_map)也可能对可能更快的查找有所帮助.根据[this](http://stackoverflow.com/a/2197015/10320)回答,`std :: undordered_map`在地图大小没有变化的情况下表现得非常好(代价是内存显着增加)用法). (2认同)