Angenommen, ich habe dieses Signal:
signals:
void progressNotification(int progress);
Ich habe erst kürzlich etwas über das Schlüsselwort emit in Qt erfahren. Bisher habe ich Signale ausgeführt, indem ich sie wie eine reguläre Funktion aufgerufen habe. Also statt:
emit progressNotification(1000 * seconds);
Ich würde schreiben:
progressNotification(1000 * seconds);
Es schien zu funktionieren, sie so aufzurufen, und alle verbundenen Slots würden ausgeführt. Verursacht die Verwendung des Schlüsselworts emit ein anderes Verhalten, oder handelt es sich nur um syntaktischen Zucker?
emit
wird nicht benötigt. Es ist jedoch seltsam, dass Sieemit
lange nach dem direkten Aufrufen von Signalen davon erfahren haben , da das Signal-Slot-System eines der ersten Dinge ist, die Sie über Qt lernen sollten.Antworten:
emit
ist nur syntaktischer Zucker. Wenn Sie sich die vorverarbeitete Ausgabe der Funktion ansehen, die ein Signal aussendet, sehen Sie, dass sieemit
einfach weg ist.Die "Magie" geschieht im generierten Code für die Signalemissionsfunktion, die Sie durch Überprüfen des von moc generierten C ++ - Codes betrachten können.
Zum Beispiel erzeugt ein
foo
Signal ohne Parameter diese Elementfunktion:Und der Code
emit foo();
wird einfach vorverarbeitetfoo();
emit
wird wie folgt definiertQt/qobjectdefs.h
(im Open-Source-Flair der Quelle):(Mit dem Define Guard können Sie Qt mit anderen Frameworks verwenden, deren Namen über die
no_keywords
QMake-Konfigurationsoption kollidieren .)quelle
emit
, die tatsächlich mehr als nichts getan hat? Ich finde, dass der 'syntaktische Zucker' in diesem Fall nur den Anfänger (oder zumindest mich, als ich ein unerfahrener Qt-Benutzer war) verwirrt - es scheint, dass mit dememit
Pseudo-Schlüsselwort etwas Magisches oder Wichtiges passiert , wenn es nichts tut all - all die Magie geschieht in einer regulären alten Funktion, diemoc
erzeugt (moc
ist die Magie für Qt-Signale und -Slots).emit
ist unnötige Dekoration, die nichts anderes tut, als wichtig zu sein.emit
teilt der Person, die den Anruf liest, mit, dass Magie bevorsteht (dh dies löst Code in Objekten aus, von denen diese Klasse möglicherweise noch nie gehört hat, und diese Aufrufe können synchron oder asynchron sein), was im Wesentlichen vollständig verloren geht, wenn Sie das Schlüsselwort weglassen. Benutze es. Es wird automatisch dokumentiert. "Anfänger" sollten Dokumente und Tutorials lesen undemit
sind immer da (in den offiziellen Dokumenten sowieso). Die Entdeckung, dass Sie die Funktion einfach aufrufen können, sollte erfolgen, nachdem Sie "das Licht gesehen" haben - zu diesem Zeitpunkt sind Sie kein Anfänger mehr.emit
"Schlüsselwort" ist. Ich denke, ich hätte es vorgezogen, eine Namenskonvention zu verwenden, wenn klargestellt werden müsste, dass ein Funktionsaufruf ein Signal ist.emit
.emit
Pseudo-Schlüsselwort-Kommentar darin bestand, klar zu machen, dass ein Signal aufgerufen wird, eine Namenskonvention dasselbe tun könnte, ohne Geheimnis und mit ähnlichen Vorteilen. Die Namenskonvention konnte von Qt nicht durchgesetzt werden (moc
könnte sie tatsächlich durchsetzen - aber ich befürworte das auch nicht), aber Qt kann die Verwendung vonemit
beiden nicht durchsetzen . Und während Sieemit
bei einem Namenskonflikt "ausschalten" können, hilft dies nicht viel, wenn Sie eine Reihe von Quelldateien haben, die es verwenden (unnötig, um zu booten).Nach 18 Monaten ... begann ich mit Kommentaren unter @ Mats Antwort und hatte schnell keinen Platz mehr. Also die Antwort.
IMO
emit
ist weder syntaktischer Zucker noch ein einfaches Schlüsselwort in dem Sinne, dassconnect
Mechanismus zu erkennen, dass es sich tatsächlich um einsignal
und handeltDas gesamte Signal- / Slot-System ist eine andere Sprache als ein einfacher Funktionsaufruf. Ich glaube, es ergibt sich aus dem Beobachtermuster. Es gibt auch einen großen Unterschied zwischen a
signal
und aslot
: Ein Signal muss nicht implementiert werden, während ein Slot sein muss !Sie gehen die Straße entlang und sehen ein brennendes Haus (ein Signal). Sie wählen 911 ( verbinden Sie das Feuersignal mit dem 911-Antwortsteckplatz ). Das Signal wurde nur ausgesendet , während der Slot von der Feuerwehr implementiert wurde. Mag ungenau sein, aber Sie bekommen die Idee. Schauen wir uns das Beispiel von OP an.
Einige Backend-Objekte wissen, wie viel Fortschritt erzielt wurde. Es könnte also einfach
emit progressNotification(...)
signalisieren. Es liegt an der Klasse, die den tatsächlichen Fortschrittsbalken anzeigt, dieses Signal aufzunehmen und darauf auszuführen. Aber wie verbindet sich die Ansicht mit diesem Signal? Willkommen beim Signal- / Slot-System von Qt. Man kann sich jetzt eine Manager-Klasse vorstellen (typischerweise eine Art Widget), die aus einem Ansichtsobjekt und einem Datenberechnungsobjekt (beide sindQObjects
) bestehtconnect (m_myDataEngine, &DataEngine::progressNotification, m_myViewObj, &SimpleView::displayProgress)
.Lassen Sie uns nicht auf die Designaspekte der Manager-Klasse eingehen, aber es genügt zu sagen, dass hier das Signal- / Slot-System glänzt. Ich kann mich darauf konzentrieren, eine sehr saubere Architektur für meine Anwendung zu entwerfen. Nicht immer, aber oft stelle ich fest, dass ich nur Signale aussende, aber Slots implementiere .
Wenn es möglich ist, eine Signalmethode zu verwenden / aufzurufen, ohne sie jemals auszusenden , bedeutet dies zwangsläufig, dass Sie diese Funktion überhaupt nicht als Signal benötigt haben.
quelle
emit
ist in der Tat nur ein leeres Makro und rein optional. Nicht so sind die Schlüsselwörtersignal
undslot
die durch die moc verarbeitet werden.signal
wird verwendet, um die Implementierung der Funktion bereitzustellen,slot
wird verwendet, um den Metaobjekteintrag so zu erstellen, dass er mit demSLOT(MySlot())
Makro oder in QML gefunden wird.emit
ist syntaktischer Zucker. Nichts wird sich jemals beschweren, wenn Sie schreibenemit i++;
(aber vielleicht Ihre Kollegen) und Sie immer noch keine Verbindung herstellen könneni++
.Die zweite Option würde bedeuten, dass Sie immer wissen, wie der Funktionsname und die Funktionsparameter lauten und dass das Objekt, an das Sie es senden, dieser bestimmten Funktion bekannt ist. Diese beiden Fälle sind nicht immer wahr, daher sind dies die beiden Hauptgründe, warum Slots und Signale erstellt wurden. "unter der Haube" Der Signal- und Slot-Mechanismus ist nur eine Tabelle mit Zeigern auf jede angeschlossene Funktion.
Schauen Sie sich auch dieses PDF an, das die Art des Signal- und Slot-Mechanismus sehr deutlich erklärt: http://www.elpauer.org/stuff/a_deeper_look_at_signals_and_slots.pdf
quelle
emit
es nur ein No-Op ist. Aber auch in diesem Fall hätte das Lesen des Fragenkörpers die Dinge klären müssen, also -1.