Cosa fa la macro Q_OBJECT? Perché tutti gli oggetti Qt necessitano di questa macro?


131

Ho appena iniziato a usare Qt e ho notato che tutte le definizioni di classe di esempio hanno la macro Q_OBJECTcome prima riga. Qual è lo scopo di questa macro preprocessore?


25
QT si riferisce a QuickTime e Qt si riferisce alla libreria C ++ chiamata Qt.
Bleadof,

Risposte:


132

Dalla documentazione di Qt :

Il Meta-Object Compiler, moc, è il programma che gestisce le estensioni C ++ di Qt.

Lo strumento moc legge un file di intestazione C ++. Se trova una o più dichiarazioni di classe che contengono la macro Q_OBJECT, produce un file sorgente C ++ contenente il codice meta oggetto per quelle classi. Tra le altre cose, è richiesto il codice meta oggetto per il meccanismo di segnali e slot, le informazioni sul tipo di runtime e il sistema di proprietà dinamico.


perché non ho bisogno di scrivere esplicitamente Q_OBJECT::connect()ma piuttosto solo connect()?
mLstudent33

19

Dice semplicemente al pre-compilatore che questa classe ha elementi gui e deve essere eseguita attraverso il 'moc', devi solo aggiungere questo alle classi che usano il meccanismo segnale / slot.
Ma verrà tranquillamente ignorato in qualsiasi altra classe - si aggiunge solo al tempo di compilazione.


3
È anche falso che tu ne abbia bisogno solo su classi che usano il meccanismo segnale / slot. L'assenza di Q_OBJECTinterruzioni qobject_caste introspezione. Può portare ad un comportamento sconcertante, quindi è una cattiva idea.
Ripristina Monica il

2
Non è vero che Q_OBJECTverrà "tranquillamente" ignorato in qualsiasi altra (non QObject) classe. Secondo lo standard C ++, introduce un comportamento indefinito dichiarando diverse funzioni membro e variabili che non vengono mai definite. Inoltre, inquina lo spazio dei nomi della tua classe con QObjectmembri specifici. Ad esempio, un po ' Q_OBJECTpotrebbe rompere una classe non correlata che contiene un metodo chiamato metaObject.
Ripristina Monica il

2
È sbagliato. Anche se probabilmente vuoi equipaggiare la maggior parte delle classi gui con la Q_OBJECTmacro, ha perfettamente senso avere classi non gui con la macro, così come le classi gui senza la macro. La macro è utile, ma non è limitata né richiesta per le classi gui.
pasbi,

9

Il MOC (compilatore meta oggetto) converte i file di intestazione inclusi macro Q_OBJECT in codice sorgente equivalente C ++. In pratica controlla il meccanismo dello slot del segnale e lo rende comprensibile al compilatore C ++


2
Questo è falso: la Q_OBJECTmacro viene espansa dal compilatore, moc non è necessario per quello. Il moc non fa nulla con la macro stessa, ma genera le definizioni delle variabili e dei metodi membri che la Q_OBJECTmacro ha dichiarato .
Ripristina Monica il

5

1 Dalla documentazione Qt di The Meta-Object System

Lo strumento moc legge un file sorgente C ++. Se trova una o più dichiarazioni di classe che contengono la macro Q_OBJECT, produce un altro file sorgente C ++ che contiene il codice meta oggetto per ciascuna di quelle classi. Questo file sorgente generato può essere # incluso nel file sorgente della classe o, più comunemente, compilato e collegato con l'implementazione della classe.

2 Dalla documentazione Qt di THE Q_OBJECT

La macro Q_OBJECT deve apparire nella sezione privata di una definizione di classe che dichiara i propri segnali e slot o che utilizza altri servizi forniti dal sistema meta-oggetto di Qt.

3 Dalla documentazione Qt di moc

Lo strumento moc legge un file di intestazione C ++. Se trova una o più dichiarazioni di classe che contengono la macro Q_OBJECT, produce un file sorgente C ++ contenente il codice meta oggetto per quelle classi. Tra le altre cose, è richiesto il codice meta oggetto per il meccanismo di segnali e slot, le informazioni sul tipo di runtime e il sistema di proprietà dinamico.

4 Dalla documentazione Qt di segnali e slot

La macro Q_OBJECT viene espansa dal preprocessore per dichiarare diverse funzioni membro implementate dal moc; se si verificano errori del compilatore sulla falsariga di "riferimento indefinito a vtable per LcdNumber", probabilmente si è dimenticato di eseguire moc o di includere l'output moc nel comando link.


2

In gcc -Epuoi vedere le macro espanse. Questo è ciò che si Q_OBJECTespande in gcc su Linux. Attenzione, questo potrebbe dipendere dalla piattaforma e potrebbe cambiare a seconda della versione di QT. Puoi vedere che non è solo un tag per il compilatore 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

La macro Q_OBJECT deve apparire nella sezione privata di una definizione di classe che dichiara i propri segnali e slot o che utilizza altri servizi forniti dal sistema meta-oggetto di Qt.


1
Questo è fuorviante: la Q_OBJECTmacro deve apparire in ogni classe da cui deriva QObject. Il tuo codice verrà sottilmente rotto quando la macro è assente, e solo perché si compila non lo rende OK.
Ripristina Monica il

@KubaOber hai un esempio di codice che viene compilato ma non funziona quando Q_OBJECTmanca la macro?
Chris,

2
Se guardi l'implementazione di Q_OBJECT, scopriresti che utilizza gli identificatori di accesso. Quindi, se la macro dovrebbe apparire in meno del private, protectedo publicprescrittori è irrilevante - è solo convenzione per metterlo alla testa della classe.
TrebledJ
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.