web-dev-qa-db-fra.com

Quand faut-il utiliser Q_OBJECT?

La documentation indique que:

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 emplacements ou qui utilise d'autres services fournis par le système de méta-objets de Qt.

Mais exactement qu'est-ce que cela signifie? Sur quelles classes dérivées de QObject puis-je l'omettre en toute sécurité? Des problèmes surviendront-ils si vous omettez Q_OBJECT sur une classe dérivée de QObject, puis héritez de celle-ci? En gros, je voudrais un peu plus d'informations sur quand je peux l'omettre de mes classes Qt.

47
Jake Petroules

Vous devez utiliser la macro Q_OBJECT pour toutes les classes non basées sur des modèles qui dérivent de QObject.

Outre les signaux et les créneaux, la macro Q_OBJECT Fournit les informations de méta-objet associées à une classe donnée.

Comme indiqué dans la documentation :

nous recommandons fortement que toutes les sous-classes de QObject utilisent la macro Q_OBJECT , qu'elles utilisent ou non réellement des signaux, des slots et des propriétés.

Supposons que nous ayons la classe suivante:

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

Sans Q_OBJECT, Les fonctionnalités système du métaobjet suivantes (entre autres) ne fonctionneront pas pour Class:

  1. qobject_cast<Class>() - en raison de métadonnées manquantes

  2. QObject::tr() - en raison de métadonnées manquantes

  3. emplacements et invocables déclarés pour la première fois dans Class, lorsqu'ils sont invoqués ou recherchés par leur nom - aucune des méthodes QMetaObject ne fonctionnera pour ces méthodes, ni le Qt 4 connect - en raison de métadonnées manquantes

  4. signaux - puisque moc ne générera pas leurs implémentations et le code ne compilera pas.

Vous pouvez bien sûr l'omettre, mais si jamais vous utilisez ces fonctionnalités, vous devrez vous rappeler de mettre la macro dans la déclaration de la classe. Il s'agit d'une pratique plutôt fragile et qu'il vaut mieux éviter. Les économies n'en valent pas la peine. Donc, n'attendez pas - ajoutez la macro Q_OBJECT À chaque classe qui dérive de QObject pour une question de politique de codage.

La macro Q_OBJECT Devrait jamais être utilisée sur les classes qui ne dérivent pas de QObject. Pour ajouter des invocables et des propriétés à ces classes, utilisez plutôt la macro Q_GADGET.

35
liaK

Si vous souhaitez utiliser des signaux/slots, vous DEVEZ inclure la macro Q_OBJECT et dériver la classe de QObject.

Sinon, vous pouvez le laisser de côté, mais cela ne fait aucun mal de l'inclure dans toutes les classes Qt gui

6
Martin Beckett

Eh bien la première partie est assez claire comme vous le savez probablement déjà .. signaux et slots, le reste du système de méta-objet est un peu moins connu. L'une des fonctionnalités les plus utiles est peut-être les propriétés dynamiques. Bien que ceux-ci aient de nombreuses utilisations, je les ai utilisés pour profiter du système d'animation de Qt QPropertyAnimation.

Il y a un peu plus d'informations sur le système de méta-objets ici: http://doc.qt.io/archives/4.6/metaobjects.html

Je pense que la ligne de fond est, si vous héritez de la hiérarchie QObject, ajoutez la macro Q_OBJECT malgré tout. C'est simple à faire et vous évitera des problèmes potentiellement déroutants sur la route.

4
Arnold Spence

Ce que @liaK a dit est correct (en bref: vous devez toujours utiliser la macro Q_OBJECT dans n'importe quelle classe qui dérive de QObject).

Une chose que je n'ai pas vue mise en évidence est que si vous ne faites pas mettez explicitement la macro Q_OBJECT puis en utilisant le parfois très pratique qobject_cast ne fonctionnera pas !!!

2
lucabox