¿Cuándo se debe usar Q_OBJECT?

La documentación establece que:

La macro Q_OBJECT debe aparecer en la sección privada de una definición de clase que declare sus propias señales y ranuras, o que use otros servicios proporcionados por el sistema de metaobjetos de Qt.

Pero exactamente qué significa eso? ¿En qué clases derivadas de QObject puedo omitirlo con seguridad? ¿Surgirán problemas si omite Q_OBJECT en una clase derivada de QObject y luego hereda de esa? Básicamente me gustaría obtener un poco más de información sobre cuándo puedo omitirlo de mis clases de Qt.

Debe usar la macro Q_OBJECT para cualquier clase que no sea de plantilla y que se derive de QObject .

Además de las señales y las ranuras, la macro Q_OBJECT proporciona la información del metaobjeto que está asociada con la clase dada.

Como se indica en la documentación :

Recomendamos encarecidamente que todas las subclases de QObject usen la macro Q_OBJECT independientemente de si usan o no señales, ranuras y propiedades.

Supongamos que tenemos la siguiente clase:

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

Sin Q_OBJECT , las siguientes características del sistema de metaobjetos (entre otros) no funcionarán para Class :

  1. qobject_cast() – debido a la falta de metadatos

  2. QObject::tr() – debido a los metadatos faltantes

  3. las máquinas tragamonedas e invokables se declararon primero en Class , cuando se invocaron o buscaron por nombre; ninguno de los métodos de QMetaObject funcionará para estos métodos, tampoco se connect la Qt 4, debido a la falta de metadatos

  4. señales – ya que moc no generará sus implementaciones y el código no se comstackrá.

Puede omitirlo, por supuesto, pero si alguna vez usa estas características, deberá recordar poner la macro en la statement de la clase. Esta es una práctica bastante frágil y es mejor evitarla. Los ahorros no valen la pena. Por lo tanto, no espere: agregue la macro Q_OBJECT a cada clase que se deriva de QObject como una cuestión de política de encoding.

La macro Q_OBJECT nunca se debe usar en clases que no se derivan de QObject . Para agregar invokables y propiedades a dichas clases, use la macro Q_GADGET lugar.

Si desea usar señales / slots, DEBE incluir la macro Q_OBJECT y derivar la clase de QObject.

De lo contrario, puedes dejarlo, pero no hace ningún daño incluirlo en todas las clases de Qt gui

Bueno, la primera parte es bastante clara, ya que probablemente ya lo sepas … señales y ranuras, el rest del sistema metaobjeto es un poco menos conocido. Quizás una de las características más útiles son las propiedades dinámicas. Aunque estos tienen muchos usos, los utilicé para aprovechar el sistema de animación QPropertyAnimation de Qt.

Hay un poco más de información sobre el sistema de metaobjetos aquí: http://doc.qt.io/archives/4.6/metaobjects.html

Creo que la conclusión es que si heredas de la jerarquía de QObject, arroja la macro Q_OBJECT independientemente. Es simple de hacer y te salvará de algunos problemas potencialmente desconcertantes en el futuro.

Lo que @liaK dijo es correcto (en resumen: siempre debe usar la macro Q_OBJECT en cualquier clase que se derive de QObject).

Una cosa que no he visto resaltada es que si no colocas explícitamente la macro Q_OBJECT , usar el qobject_cast , que a veces es muy útil , ¡no funcionará!