Bezüglich der Signale und Steckplätze fügt das Makro Q_OBJECT
eine virtuelle Funktion qt_metacall()
Deklaration in die Deklaration der Klasse ein, die später durch die moc
definiert werden soll. (Es fügt auch einige Erklärungen für die Konvertierung, aber das ist nicht so wichtig hier.)
Die moc
liest dann die Header-Datei und wenn es das Makro sieht, erzeugt er eine andere .cpp
Datei moc_headerfilename.cpp
mit den Definitionen auf die virtuellen Funktionen benannt und - Sie haben sich vielleicht gefragt, warum Sie mit der Erwähnung der signals:
in Ihrer Header-Datei ohne eine ordnungsgemäße Definition - der Signale.
Wenn also ein Signal aufgerufen wird, wird die Definition aus der Mocfile ausgeführt und QMetaObject::activate()
wird mit dem Namen des Signals und den Argumenten des Signals aufgerufen. Die Funktion activate()
ermittelt dann, welche Verbindungen hergestellt wurden, und ruft die Namen für die entsprechenden Steckplätze ab.
Dann ruft es qt_metacall
mit den Schlitznamen und die auf das Signal gegeben Argumenten und die metacall Funktion delegiert dies mit Hilfe einer großen switch
-case
Aussage zu den realen Slots.
Da es keine wirklichen Laufzeitinformationen möglich in C++ über die tatsächlichen Namen für die Signale und Slots, wie bereits bemerkt worden ist, wird diese durch die SIGNAL
und SLOT
Makros auf einfache const char*
s codiert werden (entweder mit „1“ oder "2" hinzugefügt, um Signale von den Steckplätzen zu unterscheiden.
Wie definiert in qobjectdefs.h
:
#define SLOT(a) "1"#a
#define SIGNAL(a) "2"#a
-
Die andere Sache, die Q_OBJECT
Makro tut, ist die Definition der tr()
Funktionen in Ihrem Objekt, das verwendet werden kann, Ihre Anwendung zu übersetzen.
Bearbeiten Als Sie gefragt, was die qt_metacast
tut. Es prüft, ob ein Objekt zu einer bestimmten Klasse gehört und ob es den Zeiger darauf zurückgibt. Ist dies nicht der Fall, wird 0 zurückgegeben.
Widget* w = new Widget();
Q_ASSERT(w->qt_metacast("Widget") != 0);
Q_ASSERT(w->qt_metacast("QWidget") != 0);
Q_ASSERT(w->qt_metacast("QObject") != 0);
Q_ASSERT(w->qt_metacast("UnrelatedClass") == 0);
Dies ist erforderlich, um eine Laufzeitreflexion zu ermöglichen, die andernfalls nicht möglich ist. Die Funktion wird beispielsweise in QObject::inherits(const char *)
aufgerufen und prüft einfach auf Vererbung.
dup: http://stackoverflow.com/questions/1406940/how-signal-und-slots-are-implemented-under-the-hood – elcuco