Saya baru saja mulai menggunakan Qt dan memperhatikan bahwa semua definisi kelas contoh memiliki makro Q_OBJECT
sebagai baris pertama. Apa tujuan makro preprosesor ini?
Saya baru saja mulai menggunakan Qt dan memperhatikan bahwa semua definisi kelas contoh memiliki makro Q_OBJECT
sebagai 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_OBJECT
istirahat qobject_cast
dan introspeksi. Ini dapat menyebabkan beberapa perilaku membingungkan, jadi itu ide yang buruk.
Q_OBJECT
akan "diam-diam" diabaikan di QObject
kelas (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 QObject
anggota -specific. Misalnya a Q_OBJECT
dapat memecah kelas yang tidak terkait yang kebetulan mengandung metode yang disebut metaObject
.
Q_OBJECT
makro, 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_OBJECT
makro 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_OBJECT
telah 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 -E
Anda dapat melihat makro diperluas. Inilah yang Q_OBJECT
berkembang 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_OBJECT
Makro 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_OBJECT
makro hilang?
Q_OBJECT
, Anda akan menemukan bahwa itu menggunakan penentu akses. Jadi apakah makro akan muncul di bawah private
, protected
atau public
specifier tidak relevan - itu hanya konvensi untuk menempatkannya di kepala kelas.