如何正确组织我的继承类以利用多态?

时间:2015-04-29 16:17:50

标签: c++ qt inheritance polymorphism

我正在尝试重新设计我的项目类。我无法想象事情应该如何运作。

当前实施:

function linked_node = find_neighbours(N, M, CONNECTED)

    %# which distance function
    if CONNECTED == 8
        distFunc = 'chebychev';
    else
        distFunc = 'cityblock';
    end

    linked_node=cell(N*M,1);   

      % the most important step
    for X=1:N
        for Y=1:M
            linked_node{sub2ind([N M], X,Y)} = [];
            if X - 1 > 0
                linked_node{sub2ind([N M], X,Y)}(end+1) = sub2ind([N M], X-1,Y);
                if strcmp(distFunc, 'chebychev')
                    if Y - 1 > 0
                        linked_node{sub2ind([N M], X,Y)}(end+1) = sub2ind([N M], X-1,Y-1);
                    end
                    if Y + 1 <= M
                        linked_node{sub2ind([N M], X,Y)}(end+1) = sub2ind([N M], X-1,Y+1);
                    end
                end
            end
            if X + 1 <= N
                linked_node{sub2ind([N M], X,Y)}(end+1) = sub2ind([N M], X+1,Y);
                if strcmp(distFunc, 'chebychev')
                    if Y - 1 > 0
                        linked_node{sub2ind([N M], X,Y)}(end+1) = sub2ind([N M], X+1,Y-1);
                    end
                    if Y + 1 <= M
                        linked_node{sub2ind([N M], X,Y)}(end+1) = sub2ind([N M], X+1,Y+1);
                    end
                end
            end
            if Y - 1 > 0
                linked_node{sub2ind([N M], X,Y)}(end+1) = sub2ind([N M], X,Y-1);
            end
            if Y + 1 <= M
                linked_node{sub2ind([N M], X,Y)}(end+1) = sub2ind([N M], X,Y+1);
            end
        end
    end

    end

根据选择,我创建一个项目并添加到画布......然后,一旦完成所有更改,我将其添加到class Item : public QGraphicsItem { public: typedef enum { PolygonType = QGraphicsItem::UserType + 1 } ShapeType; Item() {...} Item(const Item &copyItem) // copy constructor { m_shapeType = copyItem.getItemShape(); m_color = copyItem.getItemColor(); setPos(copyItem.pos()); ...} QRectF boundingRect() const; QPainterPath shape() const; void setItemShape(ShapeType s) { m_shapeType = s; } ShapeType getItemShape() const { return m_shapeType; } int type() const { return m_shapeType; } // this will replace the above to allow QGraphicsItem casts void setItemColor(QColor c) { m_color = c; } QColor getItemColor() const { return m_color; } .... protected: void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); QColor m_color; ShapeType m_shapeType; .... }; QPainterPath Item::shape() const { QPainterPath path; switch (m_shapeType) { case Item::PolygonType: ... break; .... } } QRectF Item::boundingRect() const { return QRectF(...); } void Item::paint(QPainter *painter, const QStyleOptionGraphicsItem */*option*/, QWidget */*widget*/) { switch (m_shapeType) { case Item::PolygonType: painter->drawPolygon(shape().toFillPolygon()); break; .... } }

所需任务:

场景的处理包含类型

的迭代
QGraphicsScene

我想要实现的目标

这是一种最小的方法,但我必须将功能扩展到扩展其他类的项目,例如Item* item1 = new Item(*renderArea->item); // make some changes on the item copy, then add it to a scene collectionView->scene()->addItem(item1); // in another function... for(int i = 0; i < collectionView->scene()->items().size(); ++i) { Item* item = new Item(*(dynamic_cast<Item*>( collectionView->scene()->items().at(i)))); ... } (无需为每个不需要它的项添加像素图)或QGraphicsPixmapItem (同样,无需为不需要它的项目添加太多开销)。

所以我在尝试:

QGraphicsSvgItem

class PolyItem : public Item
{
public:
    PolyItem(): Item()
    {
        m_shapeType = Item::PolygonType;
    }
    PolyItem(PolyItem& copy): Item::Item(copy)
    {
    }
    virtual void paint(QPainter* painter,
                       const QStyleOptionGraphicsItem* option,
                       QWidget* widget = NULL)
    {
        painter->drawPolygon(shape().toFillPolygon());
    }
};

问题:

  • 我如何让它发挥作用?当我选择一个形状时,如何创建PolygonItem的实例(并且仍然能够使用通用Item来修改其他属性,比如颜色?)

- - - - &GT;我想在类Item中创建一个不同的构造函数来创建正确的形状 - 但这似乎意味着Item需要类多边形,需要类Item ...循环依赖?

  • 更复杂的是,我如何执行上述任务,修改通用项目,迭代项目,无论形状如何?

我无法想象:

class PixMapItem : public Item, public QGraphicsPixmapItem { public: PixMapItem(): Item() { m_shapeType = Item::PixmapType; setShapeMode(QGraphicsPixmapItem::BoundingRectShape); } PixMapItem(PixMapItem& copy): Item::Item(copy) { setPixmap(copy.pixmap()); setShapeMode(QGraphicsPixmapItem::BoundingRectShape); } virtual void paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget = NULL) { painter->drawPixmap(boundingRect(), pixmap()); } };

如果我的项目是多边形类型,是否会调用collectionView->scene()->addItem(item1);函数 - 以及所有其他相关函数 - 或Item::paint()? 我是否必须插入switch-case代码来确定和转换每个类型的每个实例?

1 个答案:

答案 0 :(得分:1)

根据运行时决策创建不同的对象是Abstract factory pattern的典型用例。在您的情况下,您可以:

class ItemFactory
{
public:
    virtual Item* create() = 0;    
};

然后:

class PixMapItemFactory : public ItemFactory
{
public:
    PixMapItemFactory(/* possibly some configuration parameters */);
    Item* create();  // will return a PixMapItem instance
};

然后您可以操作ItemFactory*类型,不知道也不关心您正在创建的特定类型。它将返回Item*个实例,因此无论具体实例类型如何,您都可以更改它们的公共属性。