Home‎ > ‎Qt Mining‎ > ‎

Metaobject, reflection and qobject_cast in Qt

/*
 * filename: Metaobject, reflection and qobject_cast in Qt
 * describe: This is an article on the importance of qobject_cast and the
 *           relationship among Q_OBJECT macro, metaobject and MOC.
 * author:   Jerry Sun <jerysun007@hotmail.com>
 * date:     December 14th, 2010
 * web:      http://nl.linkedin.com/in/jerysun
 * blog:     https://sites.google.com/site/geekssmallworld
 */

There is another not only facility but also essential infrastructure in Qt -- Q_OBJECT, it's just her that makes your Qt programming life become much much easier, simply the same convenient as Java or C# programming, but it's much much more efficient without any runtime overhead, yes, it's a C++ macro!

Please don't forget macros even if you're not a class library or framework developer, never ever ever!

Q_OBJECT provides the access to metaobject that makes you can utilize such amazing features as signals and slots. Metaobject provides us such information as class name, properties, methods and so on, we call it "reflection" in C#.

The following is its definition:

#define Q_OBJECT \
public: \
    Q_OBJECT_CHECK \
    static const QMetaObject staticMetaObject; \
    Q_OBJECT_GETSTATICMETAOBJECT \
    virtual const QMetaObject *metaObject() const; \
    virtual void *qt_metacast(const char *); \
    QT_TR_FUNCTIONS \
    virtual int qt_metacall(QMetaObject::Call, int, void **); \
private:

As we see, QMetaObject is the core of the macro, what does QMetaObject for us, the Qt application developers direct?

class HisPushButton : public QPushButton { /* blah blah blah */ };
HisPushButton hBtn;
const QMetaObject *metaObj = hBtn.metaObject();
qDebug() << "class name: " << metaObj->className();
qDebug() << "class info count: " << metaObj->classInfoCount();
qDebug() << "methods: ";
// methodOffset() help you skip the methods of base class subobject
for (int i = metaObj->methodOffset(); i < metaObj->methodCount(); ++i)
    qDebug() << metaObj->method(i).methodType() << " " << metaObj->method(i).signature();

Because C++'s RTTI is not only too heavy but also can't provide all necessary information, so Qt introduced MOC(Meta Object Compiler). Please don't be confused by the name "Compiler", it's not a compiler at all, on the contrary it's actually a "code generator in preprocessing phase"!

Behind the curtain, MOC reads the header files, for instance if it reads mytest.h and find the class MyTest is derived from QObject, meanwhile there's macro Q_OBJECT inside MyTest, then MOC will generate the corresponding moc_mytest.cpp to create those meta object information for you silently:-) This is why you feel programming with Qt is the same convenient as using C#, but you still can achieve the same high performance as using the traditional C++ STL.

BTW, there are no support to GUI, threads, network, regular expression ... in STL, this is why I STRONGLY recommend you to use Qt C++ framework/library. Trust me, I am not advertising for Nokia because they don't give me even one cent ^_^

The last, but not the least is I suggest you use qobject_cast as many times as possible instead of dynamic_cast, the following is the implementation of qobject_cast():

template inline T qobject_cast(QObject *object) {
#if !defined(QT_NO_OBJECT_CHECK)
    reinterpret_cast(0)->qt_check_for_QOBJECT_macro(*reinterpret_cast(object));
#endif
    return static_cast(reinterpret_cast(0)->staticMetaObject.cast(object));
}

Well, my dear friend, I am afraid that you must've guessed the quite reason: Yes, both reinterpret_cast and static_cast all work at compiler time that avoids the huge runtime overhead of dynamic_cast.
Comments