Хранение указателей на функции-члены производных классов в карте - PullRequest
2 голосов
/ 26 декабря 2010

Я пытаюсь реализовать фабрику для двух классов 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 () соответствующего производного класса. Возможно ли это?

Спасибо, Киран

Ответы [ 3 ]

2 голосов
/ 26 декабря 2010

Хорошо, я получил ошибку.

1) не должен объявляться - виртуальный статический Shape * getInstance () = 0;- в классе Shape.

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;
0 голосов
/ 28 декабря 2010

Измените последнюю строку вашего кода на ShapeFactoryInitializer ShapeFactoryInitializer::si;, тогда он пройдет компиляцию.

0 голосов
/ 26 декабря 2010

Хотя это не очень важно для вашего вопроса, но если вы заинтересованы в современном дизайне C ++ (фабрики, умные указатели и т. Д.), Вы можете проверить эту книгу:

http://www.amazon.co.uk/Modern-Design-Applied-Generic-Patterns/dp/0201704315/ref=sr_1_20?s=books&ie=UTF8&qid=1293359949&sr=1-20

Это говорит о фабриках, как их проектировать и т. Д.

PS: я не являюсь автором книги, и мне не дали ничего взамен за публикацию этого ответа: -)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...