Que fait la macro Q_OBJECT? Pourquoi tous les objets Qt ont-ils besoin de cette macro?

131

Je viens de commencer à utiliser Qt et j'ai remarqué que toutes les définitions de classe d'exemple ont la macro Q_OBJECTcomme première ligne. Quel est le but de cette macro de préprocesseur?

Trevor Boyd Smith
la source
25
QT fait référence à QuickTime et Qt fait référence à la bibliothèque C ++ appelée Qt.
Bleadof le

Réponses:

132

De la documentation Qt :

Le compilateur de méta-objets, moc, est le programme qui gère les extensions C ++ de Qt.

L'outil moc lit un fichier d'en-tête C ++. S'il trouve une ou plusieurs déclarations de classe contenant la macro Q_OBJECT, il produit un fichier source C ++ contenant le code de méta-objet pour ces classes. Entre autres choses, le code de méta-objet est nécessaire pour le mécanisme des signaux et des slots, les informations de type d'exécution et le système de propriétés dynamiques.

Stu Mackellar
la source
pourquoi n'ai-je pas besoin d'écrire explicitement Q_OBJECT::connect()mais plutôt juste connect()?
mLstudent33
19

Il indique simplement au pré-compilateur que cette classe a des éléments d'interface graphique et doit être exécutée via le «moc», il suffit de l'ajouter aux classes qui utilisent le mécanisme signal / slot.
Mais il sera discrètement ignoré dans toutes les autres classes - cela ne fait qu'ajouter au temps de construction.

Martin Beckett
la source
3
Il est également faux que vous n'en ayez besoin que sur les classes qui utilisent le mécanisme signal / slot. L'absence de Q_OBJECTrupture qobject_castet d'introspection. Cela peut conduire à un comportement déroutant, c'est donc une mauvaise idée.
Réintégrer Monica le
2
Ce n'est pas vrai que ce Q_OBJECTsera "discrètement" ignoré dans les autres (non- QObject) classes. Selon le standard C ++, il introduit un comportement indéfini en déclarant plusieurs fonctions membres et variables qui ne sont jamais définies. Il pollue également l'espace de noms de votre classe avec des QObjectmembres spécifiques. Par exemple, un Q_OBJECTpeut bien casser une classe non liée qui contient une méthode appelée metaObject.
Réintégrer Monica le
2
C'est faux. Bien que vous souhaitiez probablement équiper la plupart des classes gui avec la Q_OBJECTmacro, il est parfaitement logique d'avoir des classes non-gui avec la macro, ainsi que des classes gui sans la macro. La macro est utile, mais ni limitée ni requise pour les classes d'interface graphique.
pasbi
9

Le MOC (compilateur de méta-objets) convertit les fichiers d'en-tête inclus de la macro Q_OBJECT en code source équivalent C ++. Il contrôle essentiellement le mécanisme de créneau de signal et le rend compréhensible pour le compilateur C ++

aditya
la source
2
C'est faux: la Q_OBJECTmacro est développée par le compilateur, moc n'est pas nécessaire pour cela. Le moc ne fait rien avec la macro elle-même, mais il génère les définitions des variables membres et des méthodes que la Q_OBJECTmacro a déclarées .
Réintégrer Monica le
5

1 De la documentation Qt du système de méta-objets

L'outil moc lit un fichier source C ++. S'il trouve une ou plusieurs déclarations de classe contenant la macro Q_OBJECT, il produit un autre fichier source C ++ qui contient le code de méta-objet pour chacune de ces classes. Ce fichier source généré est soit # inclus dans le fichier source de la classe, soit, plus généralement, compilé et lié à l'implémentation de la classe.

2 De la documentation Qt de THE Q_OBJECT

La macro Q_OBJECT doit apparaître dans la section privée d'une définition de classe qui déclare ses propres signaux et slots ou qui utilise d'autres services fournis par le système de méta-objets de Qt.

3 De la documentation Qt de moc

L'outil moc lit un fichier d'en-tête C ++. S'il trouve une ou plusieurs déclarations de classe contenant la macro Q_OBJECT, il produit un fichier source C ++ contenant le code de méta-objet pour ces classes. Entre autres choses, le code de méta-objet est nécessaire pour le mécanisme des signaux et des slots, les informations de type d'exécution et le système de propriétés dynamiques.

4 Depuis la documentation Qt des signaux et des slots

La macro Q_OBJECT est développée par le préprocesseur pour déclarer plusieurs fonctions membres qui sont implémentées par le moc; si vous obtenez des erreurs de compilation du type "référence indéfinie à vtable pour LcdNumber", vous avez probablement oublié d'exécuter le moc ou d'inclure la sortie moc dans la commande link.

Bob Zhang
la source
2

Dans gcc avec -Evous pouvez voir les macros développées. C'est ce qui se Q_OBJECTdéveloppe sur gcc sous Linux. Sachez que cela peut dépendre de la plate-forme et que cela peut changer en fonction de la version de QT. Vous pouvez voir que ce n'est pas seulement une balise pour le compilateur 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 {};
Arne
la source
0

La macro Q_OBJECT doit apparaître dans la section privée d'une définition de classe qui déclare ses propres signaux et slots ou qui utilise d'autres services fournis par le système de méta-objets de Qt.

Andrés
la source
1
Ceci est trompeur: la Q_OBJECTmacro doit apparaître dans chaque classe qui dérive de QObject. Votre code sera subtilement cassé lorsque la macro est absente, et ce n'est pas parce qu'elle se compile que cela fonctionne.
Réintégrer Monica le
@KubaOber avez-vous un exemple de code qui se compile mais ne fonctionne pas lorsque la Q_OBJECTmacro est manquante?
Chris
2
Si vous regardez l'implémentation de Q_OBJECT, vous constaterez qu'elle utilise des spécificateurs d'accès. Donc , si la macro doit apparaître dans la sous private, protectedou publicspécificateurs est hors de propos - il est convention juste pour le placer à la tête de la classe.
TrebledJ