c++ - 双分派(dispatch)和工厂模式

标签 c++ oop hierarchy double-dispatch

我目前有以下代码(不工作):

#include <iostream>
#include <vector>

class Circle;
class Rectangle;

class Shape {
private:
    Shape() {};
public:
    virtual ~Shape() {};
    friend class Circle;
    friend class Rectangle;
};

class Creator {
public:
    virtual ~Creator() {};
    virtual Shape* create() = 0;
    virtual bool equals(Shape& s) { return false; };
};

class Circle : public Shape {
private:
    Circle() : Shape() {};
public:
    class CircleCreator : public Creator {
    public:
        virtual Shape* create() { return new Circle(); };
        virtual bool equals(Shape& other_shape) { return false; };
    };
};

class Rectangle : public Shape {
private:
    Rectangle() : Shape() {};
public:
    class RectangleCreator : public Creator {
    public:
        virtual Shape* create() { return new Rectangle(); };
        virtual bool equals(Shape& other_shape) { return false; };
    };
};

int main() {
    /* First step, build the list */
    std::vector<Shape*> shapeList;
    std::vector<Shape*>::iterator it;
    Rectangle::RectangleCreator rc;
    Circle::CircleCreator cc;
    Shape* s = cc.create();
    Shape* s1 = rc.create();
    shapeList.push_back(s);
    shapeList.push_back(s1);

    /* Second step: check if we've got a shape starting from a creator */
    for (it = shapeList.begin(); it != shapeList.end(); ++it) {
        if (rc.equals(**it)) {
            std::cout << "same shape" << std::endl;
        }
    }
    return 0;
}

我的目标是使用工厂模式并避免创建新对象(如果列表中已有该对象)。我尝试使用双分派(dispatch)模式,但在这种情况下应用起来并不容易。我该怎么办?

编辑:由于代码在“关键”路径中使用,我想避免像 dynamic_cast 等 RTTI。

最佳答案

也许像这样的事情可以使用成员变量来完成

#include <iostream>
#include <vector>

enum
{
CIRCLE,
RECTANGLE
};

class Circle;
class Rectangle;

class Shape {
private:
    Shape() {};
public:
    unsigned shapeType;
    virtual ~Shape() {};
    friend class Circle;
    friend class Rectangle;
};

class Creator {
public:
unsigned shapeType;
    virtual ~Creator() {};
    virtual Shape* create() = 0;
    bool equals(Shape& s) { return (this->shapeType == s.shapeType); };
};

class Circle : public Shape {
private:
    Circle() : Shape() {shapeType=CIRCLE;};
public:
    class CircleCreator : public Creator {
    public:
        CircleCreator() {shapeType=CIRCLE;};
        virtual Shape* create() { return new Circle(); };
    };
};

class Rectangle : public Shape {
private:
    Rectangle() : Shape() {shapeType=RECTANGLE;};
public:
    class RectangleCreator : public Creator {
    public:
        RectangleCreator() {shapeType=RECTANGLE;};
        virtual Shape* create() { return new Rectangle(); };
    };
};

int main() {
    /* First step, build the list */
    std::vector<Shape*> shapeList;
    std::vector<Shape*>::iterator it;
    Rectangle::RectangleCreator rc;
    Circle::CircleCreator cc;
    Shape* s = cc.create();
    Shape* s1 = rc.create();
    shapeList.push_back(s);
    shapeList.push_back(s1);

    /* Second step: check if we've got a shape starting from a creator */
    for (it = shapeList.begin(); it != shapeList.end(); ++it) {
        if (rc.equals(**it)) {
            std::cout << "same shape" << std::endl;
        }
    }
    return 0;
}

或者这个——使用虚函数返回类型

#include <iostream>
#include <vector>

enum
{
    CIRCLE,
RECTANGLE,
UNKNOWN
};
class Circle;
class Rectangle;

class Shape {
private:
    Shape() {};
public:
    virtual ~Shape() {};
    friend class Circle;
    friend class Rectangle;
    virtual unsigned iAmA(){return UNKNOWN;};
};

class Creator {
public:
    virtual ~Creator() {};
    virtual Shape* create() = 0;
    virtual bool equals(Shape& s) { return false; };
};

class Circle : public Shape {
private:
    Circle() : Shape() {};
    virtual unsigned iAmA(){return CIRCLE;};
public:
    class CircleCreator : public Creator {
    public:
        CircleCreator() {};
        virtual Shape* create() { return new Circle(); };
        virtual bool equals(Shape& other_shape) { return (CIRCLE == other_shape.iAmA()); };
    };
};

class Rectangle : public Shape {
private:
    Rectangle() : Shape() {};
    virtual unsigned iAmA(){return RECTANGLE;};
public:
    class RectangleCreator : public Creator {
    public:
        RectangleCreator() {};
        virtual Shape* create() { return new Rectangle(); };
        virtual bool equals(Shape& other_shape) { return (RECTANGLE == other_shape.iAmA()); };
    };
};

int main() {
    /* First step, build the list */
    std::vector<Shape*> shapeList;
    std::vector<Shape*>::iterator it;
    Rectangle::RectangleCreator rc;
    Circle::CircleCreator cc;
    Shape* s = cc.create();
    Shape* s1 = rc.create();
    shapeList.push_back(s);
    shapeList.push_back(s1);

    /* Second step: check if we've got a shape starting from a creator */
    for (it = shapeList.begin(); it != shapeList.end(); ++it) {
        if (rc.equals(**it)) {
            std::cout << "same shape" << std::endl;
        }
    }
    return 0;
}

关于c++ - 双分派(dispatch)和工厂模式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28912568/

相关文章:

c++ - 在 Visual Studio 2008 Pro 和 Standard 版本中编译项目有区别吗?

c++ - 将 libnoise 库链接到 Visual Studio 2010 中的项目时遇到问题

c++ - std::vector/编程书籍神话的默认大小?

language-agnostic - "program to an interface"是什么意思?

java - 抽象类数组和 oop 设计 - Java

c++ - 使用模板 <class InputIterator> string (InputIterator begin, InputIterator end) 时出现奇怪的错误;

c++ - 结构中的默认成员值或默认构造函数参数?

perl - 在 Perl 中 Grep 一个 YAML 文件

C++ 层次结构打印练习

typescript - 在 VS Code 中显示 Typescript 类层次结构