目錄
1.基本介紹
元對象:是指用於描述另一個對象結構的對象。使用編程語言具體實現時,其實就是一個類的對象,只不過這個對象專門用於描述另一個對象而已。
Qt 的元對象系統提供的功能有:對象間的通信、運行時類型信息和動態屬性系統等
元對象系統的實現需要滿足以下三個條件:
- 該類必須繼承自 QObject
- 必須在類聲明的私有區域添加 Q_OBJECT 宏,該宏用於啓動元對象特性,然後便可使用動態特性、信號和槽等功能了
#include <QObject> class A{}; class B:public QObject,public A { Q_OBJECT };
劃重點:要使用元對象系統必須繼承自 QObject 類,且 QObject 應位於基類繼承列表中的第一位,Q_OBJECT 必須位於私有區域
2.Q_OBJECT
QObject宏定義如下:
#define Q_OBJECT \
public: \
Q_OBJECT_CHECK \
QT_WARNING_PUSH \
Q_OBJECT_NO_OVERRIDE_WARNING \
static const QMetaObject staticMetaObject; \
virtual const QMetaObject *metaObject() const; \
virtual void *qt_metacast(const char *); \
virtual int qt_metacall(QMetaObject::Call, int, void **); \
QT_TR_FUNCTIONS \
private: \
Q_OBJECT_NO_ATTRIBUTES_WARNING \
Q_DECL_HIDDEN_STATIC_METACALL static void qt_static_metacall(QObject *, QMetaObject::Call, int, void **); \
QT_WARNING_POP \
struct QPrivateSignal {}; \
QT_ANNOTATE_CLASS(qt_qobject, "")
/* qmake ignore Q_OBJECT */
#define Q_OBJECT_FAKE Q_OBJECT QT_ANNOTATE_CLASS(qt_fake, "")
裏面的QMetaObject 類描述了 QObject 及其派生類對象的所有元信息,該類是 Qt 元對象系統的核心類,通過該類的成員函數可以獲取 QObject 及其派生類對象的所有元信息,因此可以說 QMetaObject 類的對象是 Qt 中的元對象
3.元對象系統與反射機制
reflection 模式(反射模式或反射機制):是指在運行時,能獲取任意一個類對象所有類型信息、屬性、成員函數等信息的一種制
使用 Qt 反射機制的條件:
- 註冊成員函數:若希望普通成員函數能夠被反射,需要在函數聲明之前加入QObject::Q_INVOKABLE 宏
- 註冊成員變量:若希望成員變量能被反射,需要使用 Q_PROPERTY 宏
#include <QObject> #include <iostream> #include <QMetaMethod> #include <QByteArray> #include <QMetaObject> using namespace std; class A {}; class B :public QObject, public A //多繼承時,QObject必須放在第一個繼承 { Q_OBJECT public: Q_INVOKABLE B(){} //要想函數被反射,需要指定 Q_INVOKABLE 宏 Q_INVOKABLE B(int){} Q_INVOKABLE void f1(){} void f2() {} //注意:此函數不會被反射 signals: void signal1(); }; class C :public B { public: Q_INVOKABLE void f3() {} signals: void signal3(); }; int main() { B pB;C pC; const QMetaObject *pMetaObjB = pB.metaObject(); //獲取B類元對象 const QMetaObject *pMetaObjC = pC.metaObject(); //獲取C類元對象 //返回對象成員函數數量 std::cout << "類B的成員函數:" << pMetaObjB->methodCount() << std::endl; std::cout << "類C的成員函數:" << pMetaObjC->methodCount() << std::endl; //獲取對象 B所屬類中的構造函數的數量 std::cout << "類B的構造函數:" << pMetaObjB->constructorCount() << std::endl; }
QMetaObject 元對象類裏面包含多種相關的方法,可以在此類中根據需要進行使用。
4.qobject_cast 函數
使用語法:DestType* qobject_cast<DestType*>(QObject *p);
特性:
- 該函數類似於 C++中的 dynamic_cast,但執行速度比 dynamic_cast 更快;
- qobject_cast 僅適用於 QObject 及其派生類;
- 主要作用是把源類型 QObject 轉換爲尖括號中的目標類型 DesType(或者子類型),並返回指向目標類型的指針,若轉換失敗,則返回 0;
- 使用 qobject_cast 的條件:目標類型 DestType 必須繼承(直接或間接)自 QObject,並使用 Q_OBJECT 宏。