多型的底層實現機制只有兩種,一種是按照名稱查表,一種是按照位置查表,兩種方式各有利弊,c++的虛函式機制採用了按照位置查表.導致的問題是:子類很多過載的基類實現的時候開銷太大.像介面程式設計這樣子類眾多的的情況,c++的虛函式機制不適合.於是各家庫的編寫者採取自家的方法實現按照名稱查表的多型實現機制.
例如mfc:訊息對映機制,qt:元物件表機制.
在qt中,元物件表機制最大的作用就是支援訊號槽機制.當然,在此基礎上可以擴充套件出更多的功能.因為元資料是我們可以直接訪問到的,不再象虛函式機制那樣被編譯器隱藏了.
任何從qobject派生的類都包含了自己的元資料模型,一般通過巨集q_object定義的
在qt5.3.2中
#define q_object\
public: \
q_object_check \
static const qmetaobject staticmetaobject;\
virtual const qmetaobject *metaobject()const; \
virtual void *qt_metacast(const char *); \
qt_tr_functions\
virtual int qt_metacall(qmetaobject::call,int, void **); \
private: \
q_decl_hidden_static_metacall static voidqt_static_metacall(qobject *, qmetaobject::call, int, void **); \
struct qprivatesignal {};
qmetaobject型別的靜態成員變數,就是元資料的資料結構。
在struct qmetaobject中有乙個巢狀類封裝了所有的資料
structq_core_export qmetaobject
struct d;
const qmetaobject *superdata;//這是元資料代表的類的基類的元資料
const qbytearraydata *stringdata;//這是元資料的簽名標記
const uint *data;// 這是元資料的索引陣列指標
void *extradata;//這是擴充套件的元資料表的指標,一般是不用的
在#define q_object \下的三個虛函式metaobject()、qt_metacast(constchar *)、qt_metacall(qmetaobject::call, int, void **)是在moc檔案中定義的
metaobject()的作用是得到元資料表的指標
qt_metacast(constchar *)的作用是根據簽名得到相關結構的指標,返回值為void*指標
qt_metacall(qmetaobject::call,int, void **)的作用是查表然後呼叫相關的函式
巨集qt_tr_functions 是和翻譯相關的
深入淺出mfc第一篇第三章-訊息對映一節
mfc:訊息對映機制
mfc在類中實現訊息對映機制需要4個巨集,乙個用於宣告,三個用於定義
declare_message_map();//宣告訊息對映表的巨集
//定義訊息對映表的實現的3個巨集
begin_message_map(theclass,baseclass)
on_command(id,memberfxn)
defineend_message_map()
我們看到,實現的3個巨集中,需要涉及到該類的基類,而qt在使用時,只需繼承qobject和添上乙個巨集q_object。但mfc裡的訊息對映機制理解起來比qt簡單。qt的元物件表使用起來簡單。
下面構建出整個訊息對映表
首先,是三個資料結構
struct afx_msgmap //訊息對映表
afx_msgmap*pbasemessagemap; //基類的訊息對映表指標
afx_msgmap_entry*lpentries; //
struct afx_msgmap_entry // mfc 4.0 format//訊息對映實體
uintnmessage; // windows message //windows訊息
uint ncode; // control code or wm_notify code
uint nid; // control id (or 0 for windows messages)
uintnlastid; // used for entriesspecifying a range of control id's
uint nsig; // signature type (action) or pointer tomessage #
afx_pmsgpfn; // routine to call (or special value)
typedef void(ccmdtarget::*afx_pmsg)(void);//函式指標,要呼叫的函式
然後是巨集declare_message_map();//宣告訊息對映表的巨集
#definedeclare_message_map()\
staticafx_msgmap_entry _messageentries; \
staticafx_msgmap messagemap; \
virtual afx_msgmap* getmessagemap() const;
宣告乙個afx_msgmap結構的messagemap和一組訊息實體
afx_msgmap_entry_messageentries以及乙個獲取訊息表的虛函式getmessagemap()。
最後是三個定義訊息對映表的巨集begin_message_map(theclass,baseclass)、
on_command(id,memberfxn)、define end_message_map()
#definebegin_message_map(theclass, baseclass) \
afx_msgmap*theclass::getmessagemap()const \
\ //getmessagemap()的定義
afx_msgmaptheclass::messagemap= \
; \ //訊息對映表的定義
afx_msgmap_entrytheclass::_messageentries= \ //訊息對映實體定義陣列的前半部
#defineon_command(id, memberfxn) \
, // 陣列中放入乙個特定的訊息對映實體,訊息實體只獲取id和呼叫函式memberfxn引數,其他取預設值
#defineend_message_map() \
\}; //訊息對映實體定義陣列的後半部
Qt元物件系統
qmetaobject是負責元物件資訊的類,每個繼承自qobject的類都會有乙個qmetaobject物件,qobject物件共用該qmetaobject物件,給類提供遠多於c 預設的typeinfo提供的資訊。主要內容如下 1 類資訊 類 qmetaclassinfo q classinfo q...
Qt元物件系統
產生背景 qt的元物件系統為物件間的通訊提供了訊號槽機制 執行時型別資訊 動態屬性系統。核心內容 qt的元物件系統實現基於三方面 1.qobject基類。為能夠利用元物件系統的物件提供了乙個基類。2.q object巨集。用於實現元物件特性,如動態屬性 訊號槽。3.meta object compi...
Qt元物件系統
系統介紹 qt 元物件系統 meta object system qt的元物件系統基於如下三件事情 1.類 qobject,為所有需要利用元物件系統的物件提供了乙個基類。2.巨集 q object,通常可以宣告在類的私有段中,讓該類可以使用元物件的特性,比如動態屬性,訊號和槽。3.編譯器 元物件編譯...