Acabo de comenzar a usar Qt y noté que todas las definiciones de clase de ejemplo tienen la macro Q_OBJECT
como la primera línea. ¿Cuál es el propósito de esta macro de preprocesador?
Acabo de comenzar a usar Qt y noté que todas las definiciones de clase de ejemplo tienen la macro Q_OBJECT
como la primera línea. ¿Cuál es el propósito de esta macro de preprocesador?
Respuestas:
De la documentación de Qt :
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.
Q_OBJECT::connect()
sino simplemente connect()
?
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.
Q_OBJECT
rupturas qobject_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 otra QObject
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 con QObject
miembros específicos. Por ejemplo, un Q_OBJECT
bien puede romper una clase no relacionada que contiene un método llamado metaObject
.
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 ++
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 la Q_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.
En gcc with -E
puedes ver macros expandidas. Esto es lo que se Q_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.
# 11 "mainwindow.hh"
#pragma GCC diagnostic push
# 11 "mainwindow.hh"
# 11 "mainwindow.hh"
#pragma GCC diagnostic ignored "-Wsuggest-override"
# 11 "mainwindow.hh"
static const QMetaObject staticMetaObject; virtual const QMetaObject *metaObject() const; virtual void *qt_metacast(const char *); virtual int qt_metacall(QMetaObject::Call, int, void **); static inline QString tr(const char *s, cons
t char *c = nullptr, int n = -1) { return staticMetaObject.tr(s, c, n); } __attribute__ ((__deprecated__)) static inline QString trUtf8(const char *s, const char *c = nullptr, int n = -1) { return staticMetaObject.tr(s, c, n); } private:
# 11 "mainwindow.hh"
#pragma GCC diagnostic ignored "-Wattributes"
# 11 "mainwindow.hh"
__attribute__((visibility("hidden"))) static void qt_static_metacall(QObject *, QMetaObject::Call, int, void **);
# 11 "mainwindow.hh"
#pragma GCC diagnostic pop
# 11 "mainwindow.hh"
struct QPrivateSignal {};
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.
Q_OBJECT
macro 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.
Q_OBJECT
falta la macro?
Q_OBJECT
, encontrará que utiliza especificadores de acceso. Así que si la macro debe aparecer en menos del private
, protected
o public
especificadores es irrelevante - es sólo convención para colocarlo a la cabeza de la clase.