When Should Q_Object Be Used

When should Q_OBJECT be used?

You should use the Q_OBJECT macro for any non-templated classes that derive from QObject.

Besides signals and slots, the Q_OBJECT macro provides the meta object information that is associated with given class.

As stated in the documentation:

we strongly recommend that all subclasses of QObject use the Q_OBJECT macro regardless of whether or not they actually use signals, slots, and properties.

Suppose we have the following class:

class Class : public QObject {
public:
Class() {}
};

Without Q_OBJECT, the following metaobject system features (among others) will not work for Class:

  1. qobject_cast<Class>() - due to missing metadata

  2. QObject::tr() - due to missing metadata

  3. slots and invokables first declared in Class, when invoked or looked up by name - none of QMetaObject methods will work for these methods, neither will the Qt 4 connect - due to missing metadata

  4. signals - since moc won't generate their implementations and the code won't compile.

You can omit it, of course, but if you ever use these features, you'll need to remember to put the macro into the class's declaration. This is a rather brittle practice and best avoided. The savings are not worth it. So, don't wait - add the Q_OBJECT macro to every class that derives from QObject as a matter of coding policy.

The Q_OBJECT macro should never be used on classes that don't derive from QObject. To add invokables and properties to such classes, use the Q_GADGET macro instead.

Do I need to use the Q_OBJECT macro if I only use slots?

From Qt QObject class reference:

Notice that the Q_OBJECT macro is mandatory for any object that implements signals, slots or properties.

Proper use of Q_OBJECT?

Qt uses the moc compiler to produce its meta-object system (which is required for introspecting classes and allowing for signals/slots, amongst other things).

By default, qmake will do the right thing when generating and compiling the moc_*.cpp files.

Q_OBJECT and moc for inheritance

The presence of the Q_OBJECT macro marks the class for inclusion in Qt's meta-object system. If you want your class to have its own identity in this meta-object system, you must put the Q_OBJECT macro into it (and make sure it is directly or indirectly derived from QObject, naturally).

In your case of cBaseObject and cEnhancedbaseObject, if cEnhancedbaseObject does not include the Q_OBJECT macro, it will still work normally. However, as far Qt's meta-object system is concerned, objects of type cEnhancedbaseObject will be of meta-type cBaseObject. You can see that using such functions as myObject->metaObject()->className().

What does the Q_OBJECT macro do? Why do all Qt objects need this macro?

From the Qt documentation:

The Meta-Object Compiler, moc, is the
program that handles Qt's C++
extensions.

The moc tool reads a C++ header file.
If it finds one or more class
declarations that contain the Q_OBJECT
macro, it produces a C++ source file
containing the meta-object code for
those classes. Among other things,
meta-object code is required for the
signals and slots mechanism, the
run-time type information, and the
dynamic property system.

Why is it not possible to use Q_OBJECT with template classes?

It is not possible* in standard Qt, as for Qt, as for these classes moc needs to be able to pre-process the class and generate the needed meta data structures. That is done before compilation, and for a template class that means that the type is not really defined yet.

However, some things are possible:

  • A QObject can have templated methods, as long as they are not marked as invokable, slot or signal.
  • You can create a template class that inherits a QObject-derived class. It cannot have a Q_OBJECT macro or add signals, slots or properties, but it can be a useful trick, for instance to create a templated generic QAbstractItemModel.
  • You could use Verdegris instead of moc. It uses a template-based alternative to moc that generates moc-compatible code. This should also allow for templated QObjects.

*) nothing is really impossible of course... If everything else fails, you can also implement everything moc provides yourself...



Related Topics



Leave a reply



Submit