Ich habe gerade mit Qt angefangen und festgestellt, dass alle Beispielklassendefinitionen das Makro Q_OBJECT
als erste Zeile haben. Was ist der Zweck dieses Präprozessor-Makros?
Ich habe gerade mit Qt angefangen und festgestellt, dass alle Beispielklassendefinitionen das Makro Q_OBJECT
als erste Zeile haben. Was ist der Zweck dieses Präprozessor-Makros?
Antworten:
Aus der Qt-Dokumentation :
Der Meta-Object Compiler, moc, ist das Programm, das die C ++ - Erweiterungen von Qt verarbeitet.
Das moc-Tool liest eine C ++ - Headerdatei. Wenn eine oder mehrere Klassendeklarationen gefunden werden, die das Q_OBJECT-Makro enthalten, wird eine C ++ - Quelldatei erstellt, die den Metaobjektcode für diese Klassen enthält. Unter anderem wird Metaobjektcode für den Signal- und Slot-Mechanismus, die Laufzeittypinformationen und das dynamische Eigenschaftssystem benötigt.
Q_OBJECT::connect()
, sondern nur connect()
?
Es teilt dem Pre-Compiler einfach mit, dass diese Klasse GUI-Elemente enthält und über das 'moc' ausgeführt werden muss. Sie müssen dies nur Klassen hinzufügen, die den Signal- / Slot-Mechanismus verwenden.
In anderen Klassen wird es jedoch stillschweigend ignoriert - es verlängert nur die Erstellungszeit.
Q_OBJECT
Brüchen qobject_cast
und Selbstbeobachtung. Es kann zu verwirrendem Verhalten führen, daher ist es eine schlechte Idee.
Q_OBJECT
in anderen (Nicht- QObject
) Klassen "leise" ignoriert wird . Gemäß dem C ++ - Standard wird undefiniertes Verhalten eingeführt, indem mehrere Elementfunktionen und Variablen deklariert werden, die niemals definiert werden. Außerdem wird der Namespace Ihrer Klasse mit bestimmten QObject
Mitgliedern verschmutzt . Q_OBJECT
Zum Beispiel kann a eine nicht verwandte Klasse brechen, die zufällig eine aufgerufene Methode enthält metaObject
.
Q_OBJECT
Makro ausstatten möchten , ist es durchaus sinnvoll, Nicht-GUI-Klassen mit dem Makro sowie GUI-Klassen ohne das Makro zu haben. Das Makro ist nützlich, aber für GUI-Klassen weder beschränkt noch erforderlich.
Der MOC (Meta Object Compiler) konvertiert die im Q_OBJECT-Makro enthaltenen Header-Dateien in C ++ -äquivalenten Quellcode. Es steuert im Wesentlichen den Signal-Slot-Mechanismus und macht ihn für den C ++ - Compiler verständlich
Q_OBJECT
Makro wird vom Compiler erweitert, dafür wird moc nicht benötigt. Das moc macht nichts mit dem Makro selbst, sondern generiert die Definitionen der Mitgliedsvariablen und -methoden, die das Q_OBJECT
Makro deklariert hat .
1 Aus der Qt-Dokumentation des Meta-Object-Systems
Das moc-Tool liest eine C ++ - Quelldatei. Wenn eine oder mehrere Klassendeklarationen gefunden werden, die das Makro Q_OBJECT enthalten, wird eine weitere C ++ - Quelldatei erstellt, die den Metaobjektcode für jede dieser Klassen enthält. Diese generierte Quelldatei wird entweder # in die Quelldatei der Klasse aufgenommen oder in der Regel kompiliert und mit der Implementierung der Klasse verknüpft.
2 Aus der Qt-Dokumentation von THE Q_OBJECT
Das Q_OBJECT-Makro muss im privaten Abschnitt einer Klassendefinition erscheinen, die ihre eigenen Signale und Slots deklariert oder andere Dienste verwendet, die vom Metaobjektsystem von Qt bereitgestellt werden.
3 Aus der Qt-Dokumentation von moc
Das moc-Tool liest eine C ++ - Headerdatei. Wenn eine oder mehrere Klassendeklarationen gefunden werden, die das Q_OBJECT-Makro enthalten, wird eine C ++ - Quelldatei erstellt, die den Metaobjektcode für diese Klassen enthält. Unter anderem wird Metaobjektcode für den Signal- und Slot-Mechanismus, die Laufzeittypinformationen und das dynamische Eigenschaftssystem benötigt.
4 Aus der Qt-Dokumentation von Signalen und Slots
Das Q_OBJECT-Makro wird vom Präprozessor erweitert, um mehrere Mitgliedsfunktionen zu deklarieren, die vom moc implementiert werden. Wenn Sie Compilerfehler im Sinne von "undefinierter Verweis auf vtable für LcdNumber" erhalten, haben Sie wahrscheinlich vergessen, den moc auszuführen oder die moc-Ausgabe in den Link-Befehl aufzunehmen.
In gcc mit sehen -E
Sie erweiterte Makros. Dies ist, was Q_OBJECT
auf gcc unter Linux erweitert wird. Beachten Sie, dass dies möglicherweise plattformabhängig ist und sich je nach Version von QT ändern kann. Sie sehen, es ist nicht nur ein Tag für den moc-Compiler.
# 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 {};
Das Q_OBJECT-Makro muss im privaten Abschnitt einer Klassendefinition erscheinen, die ihre eigenen Signale und Slots deklariert oder andere Dienste verwendet, die vom Metaobjektsystem von Qt bereitgestellt werden.
Q_OBJECT
Makro muss in jeder Klasse erscheinen, von der abgeleitet wird QObject
. Ihr Code wird auf subtile Weise beschädigt, wenn das Makro fehlt, und nur weil es gerade kompiliert wird, ist es nicht in Ordnung.
Q_OBJECT
Makro fehlt?
Q_OBJECT
, werden Sie feststellen, dass Zugriffsspezifizierer verwendet werden. Es ist also unerheblich, ob das Makro unter dem private
, protected
oder unter den public
Bezeichnern angezeigt werden soll - es ist nur eine Konvention, es an die Spitze der Klasse zu setzen.