将派生类成员函数指针存储在映射中

3

我正在尝试为两个类Circle和Square实现一个工厂,它们都继承自Shape。

class Shape {
public: 
    virtual static
    Shape * getInstance() = 0;

};

class Circle : public Shape {        
public:
    static const std::string type;

    Shape * getInstance() {
        return new Circle;
    }
};
const std::string Circle::type = "Circle";

class Square : public Shape {        
public:
    static const std::string type;

    Shape * getInstance() {
        return new Square;
    }
};
const std::string Square::type = "Square"; 

我想创建一个以形状类型(字符串)为键,以相应派生类的getInstance()函数指针为值的映射表。这可行吗?
谢谢, Kiran

2
一个成员函数不能同时是staticvirtual。你的类到底长什么样子? - James McNellis
3个回答

3

好的,我了解了错误。

1) 不应该在 Shape 类中声明 - virtual static Shape * getInstance() = 0;。

2) 在所有其他类中,getInstance() 应该是静态的。

这是完整的实现。

class Shape {
public:

    virtual
    std::string getType() = 0;

};

class Circle : public Shape {

public:
static const std::string type;
    Circle() {

    }

    std::string getType() {
        return type;
    }

    static
    Shape * getInstance() {
        return new Circle;
    }
};
const std::string Circle::type = "Circle";

class Square : public Shape {

public:
static const std::string type;
    Square() {
    }

    std::string getType() {
        return type;
    }

    static
    Shape * getInstance() {
        return new Square;
    }
};
const std::string Square::type = "Square";

class Triangle : public Shape {

public:
static const std::string type;
    Triangle() {
    }

    std::string getType() {
        return type;
    }

    static
    Shape * getInstance() {
        return new Triangle;
    }
};
const std::string Triangle::type = "Triangle";


typedef Shape * (*getShape)();
typedef std::map<std::string, getShape > factoryMap;

class ShapeFactory {
public:
    static factoryMap shapes;
    Shape * getInstance(const std::string & type){
        factoryMap::iterator itr = shapes.find(type);
        if (itr != shapes.end()){
            return (*itr->second)();
        }
        return NULL;
    }

};

factoryMap ShapeFactory::shapes;

class ShapeFactoryInitializer {
    static ShapeFactoryInitializer si;
public:

    ShapeFactoryInitializer() {
        ShapeFactory::shapes[Circle::type] = &Circle::getInstance;
        ShapeFactory::shapes[Square::type] = &Square::getInstance;
        ShapeFactory::shapes[Triangle::type] = &Triangle::getInstance;
    }

};

ShapeFactoryInitializer ShapeFactoryInitializer::si;

1
做了一些实验后,我意识到ShapeFactoryInitializer可能不太方便。比如你有一个新的形状叫做Polygon,你就必须找到ShapeFactoryIntializer并编辑它。相反,你可以这样做。 - Kiran Mohan
1
类 AddPentagonToShapeFactory{ private: static AddPentagonToShapeFactory addPolygonToShapeFactory; AddPentagonToShapeFactory(){ ShapeFactory::shapes[Pentagon::type] = &Pentagon::getInstance; } public: //无需公开任何内容 };AddPentagonToShapeFactory AddPentagonToShapeFactory::addPolygonToShapeFactory; - Kiran Mohan
当你自己解决了问题后,回答你的问题可以得到加1分。看到那些想要回馈社区的人真是太好了! - A. Levy

0

0

将您的代码的最后一行更改为ShapeFactoryInitializer ShapeFactoryInitializer::si;,然后它就可以通过编译了。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接