QT: trouble with qobject_cast
Asked Answered
A

2

7

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...

Ananna answered 21/6, 2011 at 20:8 Comment(0)
E
15

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 :)

Eggplant answered 21/6, 2011 at 20:40 Comment(1)
Wow, can't believe I missed that... just reimplemented type() for each derived graphics item and replaced qobject_cast< DerivedItem * > with qgraphicsitem_cast< Derived Item * > and we're in business. Thanks!Ananna
B
1

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.

Bose answered 21/6, 2011 at 20:41 Comment(2)
I see why what I was trying to do is silly, but I'd like to understand why it still failed to work after making my derived items inherit from QObject. Is it because their base class has to be derived from QObject also (in this case, QGraphicsItem).Ananna
You were getting a compiler error because you were passing something of the wrong type to the function. The compiler said it couldn't find a function that accepts that type. Even though your derived object was of the correct type, the function does not return that type.Bose

© 2022 - 2024 — McMap. All rights reserved.