c++ - How do I properly organize my inheritance classes to take advantage of polymorphism? -
i trying redesign item class. having trouble picturing how things should work.
current implementation:
class item : public qgraphicsitem { public: typedef enum { polygontype = qgraphicsitem::usertype + 1 } shapetype; item() {...} item(const item ©item) // 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; } // replace above 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; .... } }
based on selections, create item , add canvas... once changes have been made, add qgraphicsscene
.
required tasks:
the processing of scene contains iterations of type
item* item1 = new item(*renderarea->item); // make changes on item copy, add scene collectionview->scene()->additem(item1); // in function... for(int = 0; < collectionview->scene()->items().size(); ++i) { item* item = new item(*(dynamic_cast<item*>( collectionview->scene()->items().at(i)))); ... }
what trying achieve
this minimal approach, have extend functionality items extend other classes, qgraphicspixmapitem
(without having add pixmap every item not need it) or qgraphicssvgitem
(again, without having add overhead items don't need it).
so trying:
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()); } };
or
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()); } };
the question:
- how make work ? how create instances of polygonitem when choose shape (and still able use generic item modify other properties, color ?)
-----> thinking of making different constructor creates correct shape, in class item - seems mean item requires class polygon requires class item... circular dependency ?
- even more complicated, how can perform tasks above, modifying generic item, iterating through items, regardless of shape ?
what can't visualize:
collectionview->scene()->additem(item1);
if item of polygon type, item::paint()
function - , other associated functions - called, or polyitem::paint()
?
have insert switch-case code determine , cast every single instance, of every single type ?
probably worth reduce item class baseitem containing adding item yourself, , functions expect item have (as pure virtual if cannot implemented without qgraphics*):
class baseitem { public: void setitemcolor(qcolor c) { m_color = c; } qcolor getitemcolor() const { return m_color; } .... protected: qcolor m_color; shapetype m_shapetype; };
then
class item : public baseitem, public qgraphicsitem class pixmapitem : public baseitem, public qgraphicspixmapitem
and forth - avoiding circular dependencies. item can referred baseitem, , provides common interface defined baseitem. each child provides specialization of interface proper qgraphics*.
problem original design item inherited qgraphicsitem while shouldn't, since plan further specialize qgraphicspixmapitem, contains qgraphicsitem in already.
edit
now, treat items baseitem when iterate through them - means baseitem has provide interface items adhere to. given examples provided in question, 1 way it:
class baseitem { virtual void addtoscene(qgraphicsscene* scene) = 0; // caller takes ownership. virtual baseitem* createcopy() = 0; };
required tasks:
the processing of scene contains iterations of type
baseitem* item1 = renderarea->item->createcopy(); // make changes on item copy, add scene item1->addtoscene(collectionview->scene());
each derived class implements interface defined baseitem, while treat items baseitem in generic operations. makes code extensible - adding new item type requires implementing derived class, existing code stays - baseitem needs designed provide interface operations common items.
class item : public baseitem, public qgraphicsitem { void addtoscene(qgraphicsscene* scene) override { scene->additem(this); } // caller takes ownership. baseitem* createcopy() override { return new item; } };
Comments
Post a Comment