Co robi makro Q_OBJECT? Dlaczego wszystkie obiekty Qt potrzebują tego makra?


132

Właśnie zacząłem używać Qt i zauważyłem, że wszystkie przykładowe definicje klas mają makro Q_OBJECTw pierwszym wierszu. Jaki jest cel tego makra preprocesora?


25
QT odnosi się do QuickTime, a Qt do biblioteki C ++ o nazwie Qt.
Bleadof

Odpowiedzi:


133

Z dokumentacji Qt :

Meta-Object Compiler, moc, to program obsługujący rozszerzenia Qt w języku C ++.

Narzędzie moc odczytuje plik nagłówkowy C ++. Jeśli znajdzie jedną lub więcej deklaracji klas, które zawierają makro Q_OBJECT, tworzy plik źródłowy C ++ zawierający kod meta-obiektu dla tych klas. Między innymi kod meta-obiektowy jest wymagany dla mechanizmu sygnałów i szczelin, informacji o typie czasu wykonywania i dynamicznego systemu właściwości.


dlaczego nie muszę pisać wprost, Q_OBJECT::connect()ale po prostu connect()?
mLstudent33

19

Po prostu mówi prekompilatorowi, że ta klasa ma elementy gui i musi zostać uruchomiona przez 'moc', którą wystarczy dodać do klas, które używają mechanizmu signal / slot.
Ale będzie po cichu zignorowany w innych klasach - po prostu wydłuża czas kompilacji.


3
Fałszem jest również to, że potrzebujesz go tylko w klasach, które używają mechanizmu sygnału / szczeliny. Brak Q_OBJECTzrywa z qobject_castintrospekcją. Może to prowadzić do pewnych kłopotliwych zachowań, więc to zły pomysł.
Unslander Monica

2
Nie jest prawdą, że Q_OBJECTbędzie on „po cichu” ignorowany w innych (nie QObject) klasach. Zgodnie ze standardem C ++ wprowadza niezdefiniowane zachowanie, deklarując kilka funkcji składowych i zmiennych, które nigdy nie zostały zdefiniowane. Zanieczyszcza również przestrzeń nazw twojej klasy QObjectskładnikami specyficznymi -specyficznymi. Np. Q_OBJECTMoże zepsuć niepowiązaną klasę, która tak się składa, że ​​zawiera wywoływaną metodę metaObject.
Unslander Monica

2
To jest źle. Chociaż prawdopodobnie chcesz wyposażyć większość klas gui w Q_OBJECTmakro, to całkowicie sensowne jest posiadanie klas innych niż gui z makrem, a także klas gui bez makra. Makro jest przydatne, ale nie jest ograniczone ani wymagane dla klas gui.
pasbi

8

MOC (kompilator meta obiektu) konwertuje pliki nagłówkowe zawarte w makrze Q_OBJECT na kod źródłowy odpowiadający C ++. Zasadniczo kontroluje mechanizm slotu sygnału i czyni go zrozumiałym dla kompilatora C ++


2
To nieprawda: Q_OBJECTmakro jest rozwijane przez kompilator, moc nie jest do tego potrzebna. Moc nie robi nic z samym makrem, ale generuje definicje zmiennych składowych i metod zadeklarowanych przez Q_OBJECTmakro .
Unslander Monica

5

1 Z dokumentacji Qt systemu meta-obiektów

Narzędzie moc odczytuje plik źródłowy C ++. Jeśli znajdzie jedną lub więcej deklaracji klas, które zawierają makro Q_OBJECT, tworzy inny plik źródłowy C ++, który zawiera kod meta-obiektu dla każdej z tych klas. Ten wygenerowany plik źródłowy jest # dołączany do pliku źródłowego klasy lub, częściej, skompilowany i połączony z implementacją klasy.

2 Z dokumentacji Qt Q_OBJECT

Makro Q_OBJECT musi pojawić się w prywatnej sekcji definicji klasy, która deklaruje własne sygnały i sloty lub korzysta z innych usług dostarczanych przez system meta-obiektów Qt.

3 Z dokumentacji Qt MOC

Narzędzie moc odczytuje plik nagłówkowy C ++. Jeśli znajdzie jedną lub więcej deklaracji klas, które zawierają makro Q_OBJECT, tworzy plik źródłowy C ++ zawierający kod meta-obiektu dla tych klas. Między innymi kod meta-obiektowy jest wymagany dla mechanizmu sygnałów i szczelin, informacji o typie czasu wykonywania i dynamicznego systemu właściwości.

4 Z dokumentacji Qt sygnałów i gniazd

Makro Q_OBJECT jest rozszerzane przez preprocesor w celu zadeklarowania kilku funkcji składowych, które są implementowane przez moc; jeśli otrzymujesz błędy kompilatora w postaci „niezdefiniowanego odwołania do vtable dla LcdNumber”, prawdopodobnie zapomniałeś uruchomić moc lub dołączyć wyjście moc do polecenia link.


2

W gcc -Emożesz zobaczyć rozwinięte makra. To właśnie Q_OBJECTrozwija się w gcc w systemie Linux. Należy pamiętać, że może to zależeć od platformy i może ulec zmianie w zależności od wersji QT. Jak widać, to nie jest tylko tag dla kompilatora moc.

# 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 {};

0

Makro Q_OBJECT musi pojawić się w prywatnej sekcji definicji klasy, która deklaruje własne sygnały i sloty lub korzysta z innych usług dostarczanych przez system meta-obiektów Qt.


2
Jest to mylące: Q_OBJECTmakro musi występować w każdej klasie, która pochodzi od QObject. Twój kod zostanie subtelnie uszkodzony, gdy makro jest nieobecne, a sam fakt kompilacji nie oznacza, że ​​wszystko jest w porządku.
Unslander Monica

@KubaOber Czy masz przykład kodu, który kompiluje się, ale nie działa, gdy Q_OBJECTbrakuje makra?
Chris

2
Jeśli spojrzysz na implementację Q_OBJECT, zobaczysz, że używa ona specyfikatorów dostępu. Tak czy makro powinien pojawić się w ramach private, protectedlub publicSpecyfikatory ma znaczenia - to tylko konwencja, aby umieścić go na czele klasy.
TrebledJ,
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.