PDA

View Full Version : qobject_cast not working right?



Mike
29th May 2006, 21:25
Hi,

I'm using QT 4.1 and can't explain the following problem. I have a method that does return either Class1 or Class2. Both inherit QObject. If I read the manual correct, than the following should result in null, but it doesn't:


...
public class Class1 : public QObject
{
...
};

public class Class2 : public QObject
{
...
};

public QObject* GetSomeData()
{
return new Class2();
}


....
// Somewhere I invoke the method above and would like
// to check if the method returned Class1 or Class2...

QObject* response = GetSomeData();
Class1* classOne = qobject_cast<Class1*>(response);
if (classOne)
{
// Method returned instance of class 1
...
}



So the problem I have in my code, is that qobject_cast never results in a null pointer... So the following if condition does allways execute... however the documentation does say something else. Anybody seen this too?

Regards,
Michael

jacek
29th May 2006, 22:00
Do you have Q_OBJECT macro in both Class1 and Class2 definition?

Mike
30th May 2006, 08:25
Matter of fact, I haven't. Is it required for the cast to work? Those classes do not have signals or slots and are just data containers. But from your comment I assume it is required to have the marco defined?

wysota
30th May 2006, 08:37
It's required so that meta-type data (for example the name and descendance tree of the class, so that it can be cast using QObject::inherits) can be associated with the class.

Mike
30th May 2006, 08:49
Ok, but what's funny then is that I changed my code because of my problem to invoke


...
response->inherits("Class1")
...


as you mentioned, and inherits does work just fine. It's just the cast that's failing.

Thanks anyway.

wysota
30th May 2006, 11:42
qobject_cast is implemented this way:


template <class T> inline T qobject_cast_helper(QObject *object, T)
{ return static_cast<T>(((T)0)->staticMetaObject.cast(object)); }

template <class T>
inline T qobject_cast(QObject *object)
{ return qobject_cast_helper<T>(object, T(0)); }

So I guess it uses QMetaObject, whereas inherits() is simply:


inline bool inherits(const char *classname) const
{ return const_cast<QObject *>(this)->qt_metacast(classname) != 0; }
What's funny, qt_metacast() is defined by... Q_OBJECT macro... and implemented by moc:


void *MYCLASS::qt_metacast(const char *_clname)
{
if (!_clname) return 0;
if (!strcmp(_clname, qt_meta_stringdata_MYCLASS))
return static_cast<void*>(const_cast<MYCLASS*>(this));
if (!strcmp(_clname, "Ui::MYCLASS"))
return static_cast<Ui::MYCLASS*>(const_cast<MYCLASS*>(this));
return BASECLASS::qt_metacast(_clname);
}

So... the bottom line is... if inherits() works for you, it's only because the base class (QObject?) has it implemented, but my guess is that it won't be possible to check if some subclass of MYCLASS inherits MYCLASS without the Q_OBJECT macro inside MYCLASS.

Mike
30th May 2006, 14:56
Great stuff... many thanks for explaining that.