ฉันเพิ่งเริ่มใช้ Qt และสังเกตเห็นว่านิยามคลาสตัวอย่างทั้งหมดมีมาโครQ_OBJECT
เป็นบรรทัดแรก จุดประสงค์ของมาโครตัวประมวลผลล่วงหน้านี้คืออะไร?
ฉันเพิ่งเริ่มใช้ Qt และสังเกตเห็นว่านิยามคลาสตัวอย่างทั้งหมดมีมาโครQ_OBJECT
เป็นบรรทัดแรก จุดประสงค์ของมาโครตัวประมวลผลล่วงหน้านี้คืออะไร?
คำตอบ:
จากเอกสาร Qt :
Meta-Object Compiler คือโปรแกรมที่จัดการส่วนขยาย C ++ ของ Qt
เครื่องมือ moc อ่านไฟล์ส่วนหัว C ++ หากพบการประกาศคลาสตั้งแต่หนึ่งคลาสขึ้นไปที่มีมาโคร Q_OBJECT จะสร้างซอร์สไฟล์ C ++ ที่มีโค้ดเมตาอ็อบเจ็กต์สำหรับคลาสเหล่านั้น เหนือสิ่งอื่นใดรหัสเมตา - อ็อบเจ็กต์จำเป็นสำหรับสัญญาณและกลไกสล็อตข้อมูลชนิดรันไทม์และระบบคุณสมบัติไดนามิก
Q_OBJECT::connect()
แต่เป็นเพียงแค่connect()
?
เพียงแค่บอกพรีคอมไพเลอร์ว่าคลาสนี้มีองค์ประกอบ gui และจำเป็นต้องรันผ่าน 'moc' คุณจะต้องเพิ่มสิ่งนี้ในคลาสที่ใช้กลไกสัญญาณ / สล็อตเท่านั้น
แต่จะถูกละเว้นอย่างเงียบ ๆ ในชั้นเรียนอื่น ๆ - เพียงแค่เพิ่มเวลาสร้าง
Q_OBJECT
แบ่งqobject_cast
และวิปัสสนา อาจนำไปสู่พฤติกรรมที่น่างงงวยดังนั้นจึงเป็นความคิดที่ไม่ดี
Q_OBJECT
จะถูกเพิกเฉยในQObject
ชั้นเรียนอื่น ๆ (ที่ไม่ใช่) ตามมาตรฐาน C ++ แนะนำพฤติกรรมที่ไม่ได้กำหนดโดยการประกาศฟังก์ชันและตัวแปรของสมาชิกหลายตัวที่ไม่เคยกำหนด นอกจากนี้ยังก่อให้เกิดเนมสเปซของชั้นเรียนของคุณด้วย - QObject
สมาชิกเฉพาะ เช่นเดียวอาจแบ่งชั้นที่ไม่เกี่ยวข้องที่เกิดขึ้นจะมีวิธีการที่เรียกว่าQ_OBJECT
metaObject
Q_OBJECT
มาโครคลาส gui ส่วนใหญ่แต่ก็เหมาะสมอย่างยิ่งที่จะมีคลาสที่ไม่ใช่ gui กับมาโครเช่นเดียวกับคลาส gui ที่ไม่มีมาโคร มาโครมีประโยชน์ แต่ไม่ จำกัด หรือไม่จำเป็นสำหรับคลาส gui
MOC (คอมไพเลอร์ออบเจ็กต์เมตา) แปลงมาโคร Q_OBJECT รวมไฟล์ส่วนหัวเป็นซอร์สโค้ดที่เทียบเท่า C ++ โดยทั่วไปจะควบคุมกลไกช่องสัญญาณและทำให้เข้าใจได้กับคอมไพเลอร์ C ++
Q_OBJECT
มาโครถูกขยายโดยคอมไพเลอร์ไม่จำเป็นต้องใช้ moc สำหรับสิ่งนั้น moc ไม่ได้ทำอะไรกับมาโครเอง แต่สร้างคำจำกัดความของตัวแปรสมาชิกและวิธีการที่Q_OBJECT
มาโครได้ประกาศไว้
1 จากเอกสาร Qt ของThe Meta-Object System
เครื่องมือ moc อ่านซอร์สไฟล์ C ++ หากพบการประกาศคลาสตั้งแต่หนึ่งคลาสขึ้นไปที่มีมาโคร Q_OBJECT จะสร้างซอร์สไฟล์ C ++ อื่นซึ่งมีโค้ดเมตาอ็อบเจ็กต์สำหรับแต่ละคลาสเหล่านั้น ซอร์สไฟล์ที่สร้างขึ้นนี้เป็น # include ในซอร์สไฟล์ของคลาสหรือโดยปกติแล้วจะรวบรวมและเชื่อมโยงกับการนำไปใช้งานของคลาส
2 จากเอกสาร Qt ของTHE Q_OBJECT
มาโคร Q_OBJECT ต้องปรากฏในส่วนไพรเวตของนิยามคลาสที่ประกาศสัญญาณและสล็อตของตัวเองหรือที่ใช้บริการอื่น ๆ ที่จัดเตรียมโดยระบบเมตาอ็อบเจ็กต์ของ Qt
3 จากเอกสาร Qt ของmoc
เครื่องมือ moc อ่านไฟล์ส่วนหัว C ++ หากพบการประกาศคลาสตั้งแต่หนึ่งคลาสขึ้นไปที่มีมาโคร Q_OBJECT จะสร้างซอร์สไฟล์ C ++ ที่มีโค้ดเมตาอ็อบเจ็กต์สำหรับคลาสเหล่านั้น เหนือสิ่งอื่นใดรหัสเมตา - อ็อบเจ็กต์จำเป็นสำหรับสัญญาณและกลไกสล็อตข้อมูลชนิดรันไทม์และระบบคุณสมบัติไดนามิก
4 จากเอกสาร Qt ของสัญญาณและสล็อต
แมโคร Q_OBJECT ถูกขยายโดยตัวประมวลผลล่วงหน้าเพื่อประกาศฟังก์ชันสมาชิกหลายอย่างที่ใช้งานโดย moc หากคุณได้รับข้อผิดพลาดของคอมไพเลอร์ตามบรรทัดของ "การอ้างอิงที่ไม่ได้กำหนดไปยัง vtable สำหรับ LcdNumber" คุณอาจลืมที่จะเรียกใช้ moc หรือรวมเอาต์พุต moc ไว้ในคำสั่งลิงก์
ใน gcc -E
คุณสามารถดูมาโครที่ขยายได้ นี่คือสิ่งที่Q_OBJECT
ขยายไปสู่ gcc บน Linux โปรดทราบว่านี่อาจขึ้นอยู่กับแพลตฟอร์มและอาจเปลี่ยนแปลงได้ขึ้นอยู่กับเวอร์ชันของ QT คุณจะเห็นว่ามันไม่ใช่แค่แท็กสำหรับคอมไพเลอร์ 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 {};
มาโคร Q_OBJECT ต้องปรากฏในส่วนไพรเวตของนิยามคลาสที่ประกาศสัญญาณและสล็อตของตัวเองหรือที่ใช้บริการอื่น ๆ ที่จัดเตรียมโดยระบบเมตาอ็อบเจ็กต์ของ Qt
Q_OBJECT
QObject
โค้ดของคุณจะเสียอย่างละเอียดเมื่อไม่มีมาโครและเพียงเพราะมันเกิดขึ้นกับการคอมไพล์ไม่ได้ทำให้มันตกลง
Q_OBJECT
มาโครหายไปหรือไม่?
Q_OBJECT
คุณจะพบว่ามันใช้ตัวระบุการเข้าถึง ดังนั้นไม่ว่าแมโครควรจะปรากฏในภายใต้private
, protected
หรือpublic
specifiers ไม่เกี่ยวข้อง - เป็นเพียงการประชุมเพื่อวางไว้ที่หัวของชั้น