94 votes

Utilisation de emit ou appel d'un signal comme s'il s'agissait d'une fonction normale dans Qt

Disons que j'ai ce signal :

signals:
    void progressNotification(int progress);

Je n'ai appris que récemment l'existence du mot-clé emit dans Qt. Jusqu'à présent, j'avais l'habitude d'exécuter les signaux en les appelant simplement comme une fonction ordinaire. Donc au lieu de :

emit progressNotification(1000 * seconds);

J'écrirais :

progressNotification(1000 * seconds);

Les appeler de cette manière semblait fonctionner, et tous les slots connectés s'exécutaient. L'utilisation du mot-clé emit entraîne-t-elle un comportement différent, ou s'agit-il simplement d'un sucre syntaxique ?

83voto

Mat Points 104488

emit est juste un sucre syntaxique. Si vous regardez la sortie prétraitée de la fonction qui émet un signal, vous verrez emit est juste parti.

La "magie" se produit dans le code généré pour la fonction d'émission du signal, que vous pouvez voir en inspectant le code C++ généré par moc.

Par exemple, un foo sans paramètres génère cette fonction membre :

void W::foo()
{
    QMetaObject::activate(this, &staticMetaObject, 0, 0);
}

Et le code emit foo(); est prétraité pour devenir simplement foo();

emit est défini dans Qt/qobjectdefs.h (dans la version open-source de la source de toute façon), comme ceci :

#ifndef QT_NO_EMIT
# define emit
#endif

(La garde de définition est pour vous permettre d'utiliser Qt avec d'autres frameworks qui ont des noms en collision via la balise no_keywords option de configuration de QMake).

5voto

NameRakes Points 324

Après 18 mois ... J'ai commencé par les commentaires sous la réponse de @Mat, et je manquais rapidement de place. D'où la réponse.

OMI emit n'est ni un sucre syntaxique ni un simple mot-clé dans le sens où

  1. Il génère du code (comme expliqué par @Mat ci-dessus),
  2. Il aide le connect mécanisme reconnaît qu'il s'agit en effet d'un signal et
  3. Il fait de votre signal une partie d'un système "plus grand", où les signaux et les réponses (slots) peuvent être exécutés de manière synchrone ou asynchrone, ou en file d'attente, en fonction de l'endroit et de la manière dont le signal a été émis. Il s'agit d'une fonctionnalité extrêmement utile du système de signaux et d'emplacements.

L'ensemble du système de signaux et de créneaux est un idiome différent de celui d'un simple appel de fonction. Je crois que cela découle du modèle de l'observateur. Il existe également une différence majeure entre un signal et un slot : un signal n'a pas à mettre en œuvre, alors qu'un créneau doit être !

Vous marchez dans la rue et vous voyez une maison en feu (un signal). Vous composez le 911 ( connecter le signal d'incendie avec le créneau d'intervention du 911 ). Le signal a été seulement émis tandis que la fente a été mis en œuvre par le service des incendies. C'est peut-être imprécis, mais vous voyez l'idée. Prenons l'exemple d'OP.

Un objet backend connaît l'état d'avancement des travaux. Il pourrait donc simplement emit progressNotification(...) signal. C'est à la classe qui affiche la barre de progression réelle de capter ce signal et de l'exécuter. Mais comment la vue se connecte-t-elle à ce signal ? Bienvenue dans le système de signaux et de créneaux de Qt. On peut maintenant concevoir une classe de gestionnaire (typiquement une sorte de widget), qui consiste en un objet de vue et un objet de calcul de données (tous deux étant des objets de type QObjects ), peut effectuer connect (m_myDataEngine, &DataEngine::progressNotification, m_myViewObj, &SimpleView::displayProgress) .

N'entrons pas dans les aspects de conception de la classe gestionnaire, mais il suffit de dire que c'est là que le système de signaux et de fentes brille. Je peux me concentrer sur la conception d'une architecture très propre pour mon application. Pas toujours, mais souvent, je constate que je peux émettent simplement des signaux mais mettent en œuvre des créneaux .

S'il est possible d'utiliser/appeler une méthode de signalisation sans jamais l'émettre alors cela implique nécessairement que vous n'avez jamais eu besoin de cette fonction comme signal en premier lieu.

-5voto

Evert Points 351

La deuxième option impliquerait que vous connaissez toujours le nom de la fonction et ses paramètres et que l'objet auquel vous l'envoyez est connu par cette fonction particulière. Ces deux cas ne sont pas toujours vrais, ce sont donc les deux raisons principales pour lesquelles les slots et les signaux ont été créés. "Sous le capot, le mécanisme des signaux et des slots est juste une table avec des pointeurs vers chaque fonction connectée.

Regardez également ce pdf qui explique très clairement la nature des signaux et le mécanisme des créneaux horaires : http://www.elpauer.org/stuff/a_deeper_look_at_signals_and_slots.pdf

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X