所謂反射,就是指物件成員的自我檢查,使用反射程式設計就可以編寫出通用的操作,可對具有各種不同結構的類進行操作;
Qt使用通用的值儲存器QVariant,就可以按照一種統一的方式來對基本型別和其他普通型別進行操作;
QMetaObject ---- 元物件模式
元物件,就是描述另一個物件結構的物件;
QMetaObject是元物件模式(MetaObject Pattern)的一個Qt實現,他提供一個QObject物件擁有的屬性和方法的資訊。
一個擁有元物件的類就可以支援反射,這是一個許多物件導向語言都具有的性質; 雖然C++不存在反射,但是Qt的元物件編譯器(moc)可以為QObject生成支援這種機制的程式碼;
QObject擁有一個成員函式,他能夠返回指向物件的QMetaObject的指標.這個函式原型:
QMetaObject * QObject::metaObject() const [virtual]
QMetaObject 提供以下方法:
className(): 將類的名稱以const char*格式返回;
superClass(): 如果存在基類的QMetaObject,則返回其指標(如果不存在,則返回0)
methodCount(): 返回類的成員函式的個數;
型別識別 和 qobject_cast
RTTI 全稱 Run Time Type Identification(執行時型別識別),如同起名字顯示一樣,是一個用來在執行時決定一個你可能僅僅擁有其基類指標的物件的實際型別的系統;
除了C++ 提供的dynamic_case 和 typeid Qt提供了 兩種執行時的型別識別機制
qobject_cast
QObject::inherits(); // Qt 不再建議使用、java風格的型別檢查函式; inherits()按樹接受一個char * 型別名,而不是型別表示式。因為該運算子需要額外的雜湊表查詢操作,所以該函式逼Qobject_cast要慢一些;
qobject_cast是一個ANSI風格的型別轉換運算子.ANSI型別轉換看來很像模板函式:
DestType* qobject_cas<DestType*>(QObject* qoptr)
型別轉換運算子根據型別和語言的特定規則與約束將表示式從一種型別轉化為另一種型別.
qobject_cast 把目標型別看做模板引數,他返回指向同一個物件的DestType的指標; 如果在執行時,實際的指標型別無法轉化成DestType* 那麼轉換就會失敗,此時返回值是NULL;
qobject_cast 實際上是一個向下轉換的運算子,類似與dynamic_cast。qobject_cast允許把一個更為常規的指標和引用轉換成某種特定的型別;
qobject_cast 的執行速度 要比 dynamic_cast 塊5到10倍;(取決與使用的編譯器)
擁有指向派生類的基類指標時,向下轉化允許呼叫在基類介面中不存在的派生類方法;;;(轉化稱為派生類指標物件,呼叫派生類函式)(qobject_cast的實現沒有使用C++ RTTI,該運算子的元物件編譯器生成的)
把qobject_cast用於非QOBject的基類時,需要把每個基類都放到一個形如Q_INTERFACES(BaseClass1 BaseClass2)的程式碼行內,並把它放到類定義中,Q_OBJECT巨集的後面;