Saya baru saja mulai menggunakan Qt dan memperhatikan bahwa semua definisi kelas contoh memiliki makro Q_OBJECTsebagai baris pertama. Apa tujuan makro preprosesor ini?
Saya baru saja mulai menggunakan Qt dan memperhatikan bahwa semua definisi kelas contoh memiliki makro Q_OBJECTsebagai baris pertama. Apa tujuan makro preprosesor ini?
Jawaban:
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.
Q_OBJECT::connect()tetapi lebih adil connect()?
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.
Q_OBJECTistirahat qobject_castdan introspeksi. Ini dapat menyebabkan beberapa perilaku membingungkan, jadi itu ide yang buruk.
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.
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.
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 ++
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 .
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.
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 {};
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.
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.
Q_OBJECTmakro hilang?
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.