Q_OBJECT makrosu ne yapar? Neden tüm Qt nesneleri bu makroya ihtiyaç duyar?


132

Qt kullanmaya yeni başladım ve tüm örnek sınıf tanımlarının Q_OBJECTilk satır olarak makroya sahip olduğunu fark ettim . Bu önişlemci makrosunun amacı nedir?


25
QT, QuickTime'ı ve Qt, Qt adlı C ++ kitaplığını ifade eder.
Bleadof

Yanıtlar:


133

Gönderen Qt belgelerinde :

Meta-Object Compiler, moc, Qt'nin C ++ uzantılarını işleyen programdır.

Moc aracı bir C ++ başlık dosyasını okur. Q_OBJECT makrosunu içeren bir veya daha fazla sınıf bildirimi bulursa, bu sınıflar için meta nesne kodunu içeren bir C ++ kaynak dosyası üretir. Diğer şeylerin yanı sıra, sinyaller ve yuva mekanizması, çalışma zamanı türü bilgisi ve dinamik özellik sistemi için meta nesne kodu gereklidir.


neden Q_OBJECT::connect()sadece açık bir şekilde yazmam gerekmiyor connect()?
mLstudent33

19

Basitçe ön derleyiciye bu sınıfın gui öğelerine sahip olduğunu ve 'moc' üzerinden çalıştırılması gerektiğini söyler, bunu yalnızca sinyal / yuva mekanizmasını kullanan sınıflara eklemeniz gerekir.
Ancak diğer sınıflarda sessizce göz ardı edilecektir - sadece yapım süresine katkıda bulunur.


3
Buna yalnızca sinyal / yuva mekanizmasını kullanan sınıflarda ihtiyacınız olduğu da yanlış. Yokluğu Q_OBJECTsonları qobject_castve iç gözlem. Bazı kafa karıştırıcı davranışlara yol açabilir, bu yüzden kötü bir fikirdir.
Monica'yı

2
Q_OBJECTDiğer (olmayan QObject) sınıflarda "sessizce" görmezden gelineceği doğru değil . C ++ standardına göre, hiçbir zaman tanımlanmayan birkaç üye işlevi ve değişkeni bildirerek tanımsız davranış sağlar. Ayrıca sınıfınızın ad alanını QObject-özel üyelerle kirletir . Örneğin, Q_OBJECTçağrılan bir yöntemi içeren ilgisiz bir sınıfı pekala bozabilir metaObject.
Monica'yı

2
Bu yanlış. Muhtemelen çoğu gui sınıfını Q_OBJECTmakro ile donatmak isteseniz de, makro ile gui olmayan sınıflara ve makro olmadan gui sınıflarına sahip olmak tamamen mantıklıdır. Makro kullanışlıdır, ancak gui sınıfları için ne sınırlı ne de zorunludur.
pasbi

9

MOC (meta nesne derleyici), Q_OBJECT makro dahil başlık dosyalarını C ++ eşdeğer kaynak koduna dönüştürür. Temel olarak sinyal yuvası mekanizmasını kontrol eder ve C ++ derleyicisine anlaşılır hale getirir.


2
Bu yanlıştır: Q_OBJECTMakro derleyici tarafından genişletilir, bunun için moc'a gerek yoktur. Moc, makronun kendisiyle hiçbir şey yapmaz, ancak makronun bildirdiği üye değişkenlerin ve yöntemlerin tanımlarını oluşturur . Q_OBJECT
Monica'yı

5

1 Meta-Nesne Sisteminin Qt belgelerinden

Moc aracı bir C ++ kaynak dosyasını okur. Q_OBJECT makrosunu içeren bir veya daha fazla sınıf bildirimi bulursa, bu sınıfların her biri için meta nesne kodunu içeren başka bir C ++ kaynak dosyası üretir. Oluşturulan bu kaynak dosya ya sınıfın kaynak dosyasına # dahil edilir ya da daha genel olarak derlenir ve sınıfın uygulamasıyla ilişkilendirilir.

2 THE Q_OBJECT'in Qt belgelerinden

Q_OBJECT makrosu, kendi sinyallerini ve yuvalarını bildiren veya Qt'nin meta-nesne sistemi tarafından sağlanan diğer hizmetleri kullanan bir sınıf tanımının özel bölümünde görünmelidir.

3 moc'un Qt belgelerinden

Moc aracı bir C ++ başlık dosyasını okur. Q_OBJECT makrosunu içeren bir veya daha fazla sınıf bildirimi bulursa, bu sınıflar için meta nesne kodunu içeren bir C ++ kaynak dosyası üretir. Diğer şeylerin yanı sıra, sinyaller ve yuva mekanizması, çalışma zamanı türü bilgisi ve dinamik özellik sistemi için meta nesne kodu gereklidir.

4 Sinyallerin ve Yuvaların Qt belgelerinden

Q_OBJECT makrosu, önişlemci tarafından moc tarafından uygulanan birkaç üye işlevi bildirmek için genişletilir; "LcdNumber için vtable'a tanımsız başvuru" satırları boyunca derleyici hataları alırsanız, muhtemelen moc'u çalıştırmayı veya moc çıktısını link komutuna eklemeyi unutmuşsunuzdur.


2

Gcc'de -Egenişletilmiş makroları görebilirsiniz. Q_OBJECTLinux'ta gcc'ye genişleyen şey budur . Bunun platforma bağlı olabileceğini ve QT sürümüne bağlı olarak değişebileceğini unutmayın. Bunun sadece moc derleyicisi için bir etiket olmadığını görebilirsiniz.

# 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

Q_OBJECT makrosu, kendi sinyallerini ve yuvalarını bildiren veya Qt'nin meta-nesne sistemi tarafından sağlanan diğer hizmetleri kullanan bir sınıf tanımının özel bölümünde görünmelidir.


1
Bu yanıltıcıdır: Q_OBJECTMakro, türetilen her sınıfta görünmelidir QObject. Makro yokken kodunuz ince bir şekilde kırılır ve sırf derlenmek onu tamamlamaz.
Monica'yı

@KubaOber, Q_OBJECTmakro eksik olduğunda derleyen ancak çalışmayan bir kod örneğiniz var mı?
Chris

2
Uygulamasına bakarsanız, Q_OBJECTerişim belirticilerini kullandığını görürsünüz. Yani makro altında görünmesinin gerekip gerekmediğini private, protectedveya publicbelirteçleri önemsizdir - sınıfın başında yerleştirmek için sadece bir âdet.
ÜçlüJ
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.