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.