Casts and Qt

1 post / 0 new
alfkil
alfkil's picture
Offline
Last seen: 4 months 3 days ago
Joined: 2011-05-10 22:02
Casts and Qt

I'm having another weird problem... This time it has to do with type casting and metatypes in Qt. There is this function qobject_cast, which is defined as such:

  1. template <class T>
  2. inline T qobject_cast(QObject *object)
  3. { return qobject_cast_helper<T>(object, T(0)); }
  4. //...
  5. template <class T> inline T qobject_cast_helper(QObject *object, T)
  6. { return static_cast<T>(((T)0)->staticMetaObject.cast(object)); }
  7.  
  8. //and somewhere else
  9. QObject *QMetaObject::cast(QObject *obj) const
  10. {
  11. if (obj) {
  12. const QMetaObject *m = obj->metaObject();
  13. do {
  14. if (m == this)
  15. return const_cast<QObject*>(obj);
  16. } while ((m = m->d.superdata));
  17. }
  18. return 0;
  19. }

Now, in the gui library, this code is called to determine, if the layout is the child of another layout:

  1. if (parent()) {
  2. QLayout *parentLayout = qobject_cast<QLayout*>(parent());
  3. if (!parentLayout) {
  4. //complain that the parent is not a layout (and crash)

In this case the parent is a QHBoxLayout, which is a child of QLayout. Now, what happens is, that two different programs call this code. One is a small test of the mainwindow abilities in libQtGui, another one is the demo browser using libQtWebKit. But this is all so, basically it is the same condition in both cases. BUT the first case succeeds, and the second fails. That is, in the first case qobject_cast returns a pointer to the QLayout version of parent, in the second it returns a NULL pointer.

What happens is, that QMetaObject::cast() is called with "this" pointing at 0x0. Now, I can do this to make it work:

REPLACE
QLayout *parentLayout = qobject_cast(parent());
WITH
QLayout *parentLayout = (QLayout *)(((QLayout *)0)->staticMetaObject).cast(parent());

Now ::cast() is called with the real pointer.

My question is: Why does this replacement work when the original fails?? And why does this very same code work for one program UNDER THE EXACT SAME CONDITIONS but not another?

NOTE: This is all Qt code, basically I have modified nothing, except for the replacement code above.