7
votes

I have derived QGraphicsItem and QGraphicsScene classes. I want the items to be able to call scene() and get a derviedGraphicsItem * instead of a QGraphicsItem *, so I reimplemented QGraphicsScene::itemAt to return a derived pointer.

DerivedItem* DerivedScene::itemAt( const QPointF &position, const QTransform &dt ) const
{
    return qobject_cast< DerivedItem * >(
            QGraphicsScene::itemAt(position, dt) );
}

I get the following error (Qt 4.6, GCC 4.4.3 on Ubuntut 10.4)

scene.cpp: In member function ‘DerivedItem* DerivedScene::itemAt(qreal, qreal, const QTransform&) const’:
scene.cpp:28: error: no matching function for call to ‘qobject_cast(QGraphicsItem*)’

I then noticed QGraphicsItem doesn't inherit QObject, so I made my derived QGraphicsItem class have multiple inheritance from QObject and QGraphicsItem, and after adding the Q_OBJECT macro and rebuilding the project I get the same error.

Am I going about this the wrong way? I know it's supposed to be bad design to try to cast a parent class as a child, but in this case it seems like what I want, since my derived item class has new functionality and its objects need a way to call that new functionality on items around themselves, and asking the items scene object with itemAt() seems like the best way - but I need itemAt() to return a pointer of the right type. I can get around this by having the derived items cast the QGraphicsItem * returned by QGraphicsScene::itemAt() using dynamic_cast, but I don't really understand why that works and not qobject_cast, or the benefits or disadvantages to using dynamic_cast vs. qobject_cast.

EDIT: forgot to mention that I also reimplemented QGraphicsItem::scene() in my derived class to return a DerivedScene *, as

DerivedScene* DerivedItem::scene() const
{
    return qobject_cast< DerivedScene * >( QGraphicsItem::scene() );
}

but this doesn't appear to be causing a compilation error...

2

2 Answers

15
votes

There is no point in inheriting from QObject just for casting. The advantage of qobject_cast over dynamic cast is summed up pretty much in the qobject_cast documentation:

The qobject_cast() function behaves similarly to the standard C++ dynamic_cast(), with the advantages that it doesn't require RTTI support and it works across dynamic library boundaries.

It's nice to have and useful if you have QObjects, but not worth to inherit from QObject if it is all you want from QObject.

Also, for QGraphicsIems there is qgraphicsitem_cast, which should do exactly what you want :)

1
votes

You have to pass a QObject pointer to qobject_cast() and QGraphicsScene::itemAt returns a QGraphicsItem pointer. Since, as you mentioned, QGraphicsItem does not derive from QObject, the complier gave you that error.