¿Qué hace la macro Q_OBJECT? ¿Por qué todos los objetos Qt necesitan esta macro?
131
Acabo de comenzar a usar Qt y noté que todas las definiciones de clase de ejemplo tienen la macro Q_OBJECTcomo la primera línea. ¿Cuál es el propósito de esta macro de preprocesador?
El compilador Meta-Object, moc, es el programa que maneja las extensiones C ++ de Qt.
La herramienta moc lee un archivo de encabezado C ++. Si encuentra una o más declaraciones de clase que contienen la macro Q_OBJECT, genera un archivo fuente C ++ que contiene el código del metaobjeto para esas clases. Entre otras cosas, se requiere un código de metaobjeto para el mecanismo de señales y ranuras, la información del tipo de tiempo de ejecución y el sistema de propiedades dinámicas.
¿Por qué no necesito escribir explícitamente Q_OBJECT::connect()sino simplemente connect()?
mLstudent33
19
Simplemente le dice al precompilador que esta clase tiene elementos de interfaz gráfica de usuario y debe ejecutarse a través del 'moc', solo necesita agregar esto a las clases que usan el mecanismo de señal / ranura.
Pero será ignorado silenciosamente en cualquier otra clase, solo aumenta el tiempo de construcción.
También es falso que solo lo necesite en clases que usan el mecanismo de señal / ranura. La ausencia de Q_OBJECTrupturas qobject_caste introspección. Puede conducir a un comportamiento desconcertante, por lo que es una mala idea.
Mónica
2
No es cierto que Q_OBJECTse ignorará "en silencio" en cualquier otra QObjectclase (no ). De acuerdo con el estándar C ++, introduce un comportamiento indefinido al declarar varias funciones y variables miembro que nunca se definen. También contamina el espacio de nombres de su clase con QObjectmiembros específicos. Por ejemplo, un Q_OBJECTbien puede romper una clase no relacionada que contiene un método llamado metaObject.
Mónica
2
Eso está mal. Aunque probablemente desee equipar la mayoría de las clases gui con la Q_OBJECTmacro, tiene mucho sentido tener clases no gui con la macro, así como clases gui sin la macro. La macro es útil, pero no está limitada ni es necesaria para las clases gui.
pasbi
9
El MOC (compilador de metaobjetos) convierte los archivos de encabezado incluidos en la macro Q_OBJECT en código fuente equivalente de C ++. Básicamente controla el mecanismo de ranura de señal y lo hace comprensible para el compilador de C ++
Eso es falso: el Q_OBJECTcompilador expande la macro, no se necesita moc para eso. El moc no hace nada con la macro en sí, pero genera las definiciones de las variables miembro y los métodos que la Q_OBJECTmacro ha declarado .
Mónica
5
1 De la documentación de Qt del sistema Meta-Object
La herramienta moc lee un archivo fuente C ++. Si encuentra una o más declaraciones de clase que contienen la macro Q_OBJECT, genera otro archivo fuente C ++ que contiene el código del metaobjeto para cada una de esas clases. Este archivo fuente generado # se incluye en el archivo fuente de la clase o, más habitualmente, se compila y vincula con la implementación de la clase.
La macro Q_OBJECT debe aparecer en la sección privada de una definición de clase que declara sus propias señales y ranuras o que utiliza otros servicios proporcionados por el sistema de metaobjetos de Qt.
La herramienta moc lee un archivo de encabezado C ++. Si encuentra una o más declaraciones de clase que contienen la macro Q_OBJECT, genera un archivo fuente C ++ que contiene el código del metaobjeto para esas clases. Entre otras cosas, se requiere un código de metaobjeto para el mecanismo de señales y ranuras, la información del tipo de tiempo de ejecución y el sistema de propiedades dinámicas.
El preprocesador expande la macro Q_OBJECT para declarar varias funciones miembro que implementa el moc; si obtiene errores del compilador en la línea de "referencia indefinida a vtable para LcdNumber", probablemente haya olvidado ejecutar el moc o incluir la salida de moc en el comando de enlace.
En gcc with -Epuedes ver macros expandidas. Esto es lo que se Q_OBJECTexpande en gcc en Linux. Tenga en cuenta que esto puede depender de la plataforma y puede cambiar según la versión de QT. Puede ver que no es solo una etiqueta para el compilador de moc.
La macro Q_OBJECT debe aparecer en la sección privada de una definición de clase que declara sus propias señales y ranuras o que utiliza otros servicios proporcionados por el sistema de metaobjetos de Qt.
Esto es engañoso: la Q_OBJECTmacro debe aparecer en cada clase de la que se deriva QObject. Su código se romperá sutilmente cuando la macro esté ausente, y solo porque se compila no lo hace correcto.
Vuelva a instalar Mónica
@KubaOber, ¿tiene un ejemplo de código que se compila pero no funciona cuando Q_OBJECTfalta la macro?
Chris
2
Si observa la implementación de Q_OBJECT, encontrará que utiliza especificadores de acceso. Así que si la macro debe aparecer en menos del private, protectedo publicespecificadores es irrelevante - es sólo convención para colocarlo a la cabeza de la clase.
Respuestas:
De la documentación de Qt :
fuente
Q_OBJECT::connect()
sino simplementeconnect()
?Simplemente le dice al precompilador que esta clase tiene elementos de interfaz gráfica de usuario y debe ejecutarse a través del 'moc', solo necesita agregar esto a las clases que usan el mecanismo de señal / ranura.
Pero será ignorado silenciosamente en cualquier otra clase, solo aumenta el tiempo de construcción.
fuente
Q_OBJECT
rupturasqobject_cast
e introspección. Puede conducir a un comportamiento desconcertante, por lo que es una mala idea.Q_OBJECT
se ignorará "en silencio" en cualquier otraQObject
clase (no ). De acuerdo con el estándar C ++, introduce un comportamiento indefinido al declarar varias funciones y variables miembro que nunca se definen. También contamina el espacio de nombres de su clase conQObject
miembros específicos. Por ejemplo, unQ_OBJECT
bien puede romper una clase no relacionada que contiene un método llamadometaObject
.Q_OBJECT
macro, tiene mucho sentido tener clases no gui con la macro, así como clases gui sin la macro. La macro es útil, pero no está limitada ni es necesaria para las clases gui.El MOC (compilador de metaobjetos) convierte los archivos de encabezado incluidos en la macro Q_OBJECT en código fuente equivalente de C ++. Básicamente controla el mecanismo de ranura de señal y lo hace comprensible para el compilador de C ++
fuente
Q_OBJECT
compilador expande la macro, no se necesita moc para eso. El moc no hace nada con la macro en sí, pero genera las definiciones de las variables miembro y los métodos que laQ_OBJECT
macro ha declarado .1 De la documentación de Qt del sistema Meta-Object
La herramienta moc lee un archivo fuente C ++. Si encuentra una o más declaraciones de clase que contienen la macro Q_OBJECT, genera otro archivo fuente C ++ que contiene el código del metaobjeto para cada una de esas clases. Este archivo fuente generado # se incluye en el archivo fuente de la clase o, más habitualmente, se compila y vincula con la implementación de la clase.
2 De la documentación de Qt de THE Q_OBJECT
La macro Q_OBJECT debe aparecer en la sección privada de una definición de clase que declara sus propias señales y ranuras o que utiliza otros servicios proporcionados por el sistema de metaobjetos de Qt.
3 De la documentación de Qt de moc
La herramienta moc lee un archivo de encabezado C ++. Si encuentra una o más declaraciones de clase que contienen la macro Q_OBJECT, genera un archivo fuente C ++ que contiene el código del metaobjeto para esas clases. Entre otras cosas, se requiere un código de metaobjeto para el mecanismo de señales y ranuras, la información del tipo de tiempo de ejecución y el sistema de propiedades dinámicas.
4 De la documentación de Qt de señales y ranuras
El preprocesador expande la macro Q_OBJECT para declarar varias funciones miembro que implementa el moc; si obtiene errores del compilador en la línea de "referencia indefinida a vtable para LcdNumber", probablemente haya olvidado ejecutar el moc o incluir la salida de moc en el comando de enlace.
fuente
En gcc with
-E
puedes ver macros expandidas. Esto es lo que seQ_OBJECT
expande en gcc en Linux. Tenga en cuenta que esto puede depender de la plataforma y puede cambiar según la versión de QT. Puede ver que no es solo una etiqueta para el compilador de moc.fuente
La macro Q_OBJECT debe aparecer en la sección privada de una definición de clase que declara sus propias señales y ranuras o que utiliza otros servicios proporcionados por el sistema de metaobjetos de Qt.
fuente
Q_OBJECT
macro debe aparecer en cada clase de la que se derivaQObject
. Su código se romperá sutilmente cuando la macro esté ausente, y solo porque se compila no lo hace correcto.Q_OBJECT
falta la macro?Q_OBJECT
, encontrará que utiliza especificadores de acceso. Así que si la macro debe aparecer en menos delprivate
,protected
opublic
especificadores es irrelevante - es sólo convención para colocarlo a la cabeza de la clase.