Je viens de commencer à utiliser Qt et j'ai remarqué que toutes les définitions de classe d'exemple ont la macro Q_OBJECT
comme première ligne. Quel est le but de cette macro de préprocesseur?
Je viens de commencer à utiliser Qt et j'ai remarqué que toutes les définitions de classe d'exemple ont la macro Q_OBJECT
comme première ligne. Quel est le but de cette macro de préprocesseur?
Réponses:
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.
Q_OBJECT::connect()
mais plutôt juste connect()
?
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.
Q_OBJECT
rupture qobject_cast
et d'introspection. Cela peut conduire à un comportement déroutant, c'est donc une mauvaise idée.
Q_OBJECT
sera "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 QObject
membres spécifiques. Par exemple, un Q_OBJECT
peut bien casser une classe non liée qui contient une méthode appelée metaObject
.
Q_OBJECT
macro, 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.
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 ++
Q_OBJECT
macro 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_OBJECT
macro a déclarées .
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.
Dans gcc avec -E
vous pouvez voir les macros développées. C'est ce qui se Q_OBJECT
dé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 {};
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.
Q_OBJECT
macro 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.
Q_OBJECT
macro est manquante?
Q_OBJECT
, vous constaterez qu'elle utilise des spécificateurs d'accès. Donc , si la macro doit apparaître dans la sous private
, protected
ou public
spécificateurs est hors de propos - il est convention juste pour le placer à la tête de la classe.