Apa yang dilakukan makro Q_OBJECT? Mengapa semua objek Qt membutuhkan makro ini?


131

Saya baru saja mulai menggunakan Qt dan memperhatikan bahwa semua definisi kelas contoh memiliki makro Q_OBJECTsebagai baris pertama. Apa tujuan makro preprosesor ini?


25
QT merujuk ke QuickTime dan Qt merujuk ke pustaka C ++ yang disebut Qt.
— Bleadof

Jawaban:


132

Dari dokumentasi Qt :

Meta-Object Compiler, moc, adalah program yang menangani ekstensi Q ++ Ct.

Alat moc membaca file header C ++. Jika ia menemukan satu atau beberapa deklarasi kelas yang berisi makro Q_OBJECT, itu menghasilkan file sumber C ++ yang berisi kode objek-meta untuk kelas-kelas tersebut. Antara lain, kode objek-meta diperlukan untuk mekanisme sinyal dan slot, informasi tipe run-time, dan sistem properti dinamis.


mengapa saya tidak perlu menulis secara eksplisit Q_OBJECT::connect()tetapi lebih adil connect()?
— mLstudent33

19

Ini hanya memberitahu pra-kompiler bahwa kelas ini memiliki elemen gui dan perlu dijalankan melalui 'moc' Anda hanya perlu menambahkan ini ke kelas yang menggunakan mekanisme sinyal / slot.
Tapi itu akan diabaikan dengan tenang di kelas lain - itu hanya menambah waktu membangun.


3
Ini juga salah bahwa Anda hanya membutuhkannya di kelas yang menggunakan mekanisme sinyal / slot. Tidak adanya Q_OBJECTistirahat qobject_castdan introspeksi. Ini dapat menyebabkan beberapa perilaku membingungkan, jadi itu ide yang buruk.
— Pasang kembali Monica

2
Tidak benar bahwa Q_OBJECTakan "diam-diam" diabaikan di QObjectkelas (non- ) lainnya. Menurut standar C ++, ini memperkenalkan perilaku yang tidak terdefinisi dengan mendeklarasikan beberapa fungsi anggota dan variabel yang tidak pernah didefinisikan. Itu juga mencemari namespace kelas Anda dengan QObjectanggota -specific. Misalnya a Q_OBJECTdapat memecah kelas yang tidak terkait yang kebetulan mengandung metode yang disebut metaObject.
— Pasang kembali Monica

2
Itu salah. Meskipun Anda mungkin ingin melengkapi sebagian besar kelas gui dengan Q_OBJECTmakro, masuk akal untuk memiliki kelas non-gui dengan makro, serta kelas gui tanpa makro. Makro berguna, tetapi tidak terbatas pada atau diperlukan untuk kelas gui.
— pasbi

9

MOC (compiler objek meta) mengkonversi makro Q_OBJECT termasuk file header ke kode sumber setara C ++. Ini pada dasarnya mengontrol mekanisme slot sinyal, dan membuatnya dapat dimengerti oleh kompiler C ++


2
Itu salah: Q_OBJECTmakro diperluas oleh kompiler, moc tidak diperlukan untuk itu. MSC tidak melakukan apa pun dengan makro itu sendiri, tetapi ia menghasilkan definisi variabel anggota dan metode yang Q_OBJECTtelah dinyatakan makro .
— Pasang kembali Monica

5

1 Dari dokumentasi Qt The Meta-Object System

Alat moc membaca file sumber C ++. Jika ia menemukan satu atau beberapa deklarasi kelas yang berisi makro Q_OBJECT, itu menghasilkan file sumber C ++ lain yang berisi kode objek-meta untuk masing-masing kelas tersebut. File sumber yang dihasilkan ini # dimasukkan ke dalam file sumber kelas atau, lebih biasanya, dikompilasi dan dihubungkan dengan implementasi kelas.

2 Dari dokumentasi Qt THE Q_OBJECT

Makro Q_OBJECT harus muncul di bagian pribadi dari definisi kelas yang menyatakan sinyal dan slotnya sendiri atau yang menggunakan layanan lain yang disediakan oleh sistem objek-metrik Qt.

3 Dari dokumentasi Qt moc

Alat moc membaca file header C ++. Jika ia menemukan satu atau beberapa deklarasi kelas yang berisi makro Q_OBJECT, itu menghasilkan file sumber C ++ yang berisi kode objek-meta untuk kelas-kelas tersebut. Antara lain, kode objek-meta diperlukan untuk mekanisme sinyal dan slot, informasi tipe run-time, dan sistem properti dinamis.

4 Dari dokumentasi Qt untuk Sinyal dan Slot

Makro Q_OBJECT diperluas oleh preprocessor untuk mendeklarasikan beberapa fungsi anggota yang diimplementasikan oleh moc; jika Anda mendapatkan kesalahan kompiler di sepanjang baris "referensi tidak terdefinisi ke vtable untuk LcdNumber", Anda mungkin lupa untuk menjalankan moc atau untuk memasukkan output moc dalam perintah tautan.


2

Dalam gcc dengan -EAnda dapat melihat makro diperluas. Inilah yang Q_OBJECTberkembang ke gcc di Linux. Ketahuilah, ini mungkin bergantung pada platform dan mungkin berubah tergantung pada versi QT. Anda dapat melihatnya bukan hanya tag untuk kompiler 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 harus muncul di bagian pribadi dari definisi kelas yang menyatakan sinyal dan slotnya sendiri atau yang menggunakan layanan lain yang disediakan oleh sistem objek-metrik Qt.


1
Ini menyesatkan: Q_OBJECTMakro harus muncul di setiap kelas yang berasal dari QObject. Kode Anda akan rusak secara halus ketika makro tidak ada, dan hanya karena kompilasi yang terjadi tidak membuatnya OK.
— Pasang kembali Monica

@KubaOber apakah Anda memiliki contoh kode yang mengkompilasi tetapi tidak berfungsi ketika Q_OBJECTmakro hilang?
— Chris

2
Jika Anda melihat implementasi Q_OBJECT , Anda akan menemukan bahwa itu menggunakan penentu akses. Jadi apakah makro akan muncul di bawah private, protectedatau publicspecifier tidak relevan - itu hanya konvensi untuk menempatkannya di kepala kelas.
— TrebledJ
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.