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?

Trevor Boyd Smith
sumber
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.

Stu Mackellar
sumber
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.

Martin Beckett
sumber
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 ++

aditya
sumber
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.

Bob Zhang
sumber
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 {};
Arne
sumber
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.

Andres
sumber
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