mfc中大量使用了begin_***_map這樣的巨集,以及對映進行查詢優化,例如訊息對映,ole命令對映,以及介面等等。每個對映包含乙個指向基類的對映的指標。這樣,當乙個類需要根據一定的條件查詢乙個物件時,它會查詢本類物件,如果沒有找到,那麼會查詢基類,直到根基類。這類查詢包含windows訊息,命令,事件和ole命令的分發,和物件實現的介面的查詢等等。
下面是函式bool cwnd::onwndmsg(uint message, wparam wparam, lparam lparam, lresult* presult)的部分**,演示了如何根據訊息的id查詢處理函式。
const afx_msgmap* pmessagemap; pmessagemap = getmessagemap();uint ihash; ihash = (loword((dword_ptr)pmessagemap) ^ message) & (ihashmax-1);afxlockglobals(crit_winmsgcache);afx_msg_cache* pmsgcache; pmsgcache = &_afxmsgcache[ihash];const afx_msgmap_entry* lpentry;if (message == pmsgcache->nmsg && pmessagemap == pmsgcache->pmessagemap)else}elselpentry++; // keep looking past this one}}}pmsgcache->lpentry = null;afxunlockglobals(crit_winmsgcache);return false;}ldispatch:注意
對查詢結果的快取可以提高查詢的效率。
不要被mfc起的名字欺騙了,從資料結構上來說,查詢是順序的,而不是使用cmap類使用的雜湊技術,所以上面的**中使用雜湊技術,快取最近的查詢結果和把最常用的對映項放在最前面通常有助於提高效率。
使用查詢對映的好處是,可以方便地在派生類中擴充套件和覆蓋對映(例如重新實現idispatch),而不用重寫/過載查詢函式(訊息和命令的分發,或者介面的查詢);也可以不使用對資源消耗很大的虛函式表。(儘管如此,cwnd類還是有無數個虛函式,並且不出意外地看到,在mfc6到mfc7的公升級中又有增加)
使用查詢對映的壞處麼,當然是理解上的問題和效能上的損失了。
mfc在把控制代碼封裝成物件方面不遺餘力,為了保證同一執行緒內物件<->控制代碼對映是一對一的,建立了各種各樣的控制代碼對映,視窗,gdi物件,選單諸如此類。為了封裝getdlgitem,selectobject這樣的api返回的臨時的控制代碼,mfc還產生臨時的物件<->控制代碼對映。控制代碼對映使得getparentframe這樣的函式可以實現。
cframewnd* cwnd::getparentframe() constreturn null;}
_afxwin_inline cwnd* cwnd::getparent() const看到了麼,它首先呼叫api getparent,然後去本執行緒的視窗<->控制代碼對映查詢物件指標,然後呼叫cwnd::isframewnd來決定物件是否是框架。(謝天謝地,這個函式是用虛函式而不是用cobject::iskindof,不然又得遍歷一遍執行時類資訊)。因為物件和控制代碼的對應的唯一性,所以可以找到唯一的父框架視窗物件。
在一些經常呼叫的函式裡面也使用到這個對映
lresult callbackafxwndproc(hwnd hwnd, uint nmsg, wparam wparam, lparam lparam)也就是說,它要遍歷一遍afxmaphwnd()返回的物件裡面的永久的控制代碼對映。而這個函式在每個訊息到達的時候都要呼叫。這是mfc應用程式效能損失的原因之一。
mfc為了快速和方便地開發作了很多任務作,例如上述的兩種對映,但是效能方面有所損失。開發應用程式時,需要在快速方便和效能損失方面的權衡。(話是這麼說,但是根據摩爾定律,再過兩年我的話就成廢話了)
分析MFC中的對映
mfc中大量使用了begin map這樣的巨集,以及對映進行查詢優化,例如訊息對映,ole命令對映,以及介面等等。每個對映包含乙個指向基類的對映的指標。這樣,當乙個類需要根據一定的條件查詢乙個物件時,它會查詢本類物件,如果沒有找到,那麼會查詢基類,直到根基類。這類查詢包含windows訊息,命令,事...
分析MFC中的對映
mfc中大量使用了begin map這樣的巨集,以及對映進行查詢優化,例如訊息對映,ole命令對映,以及介面等等。每個對映包含乙個指向基類的對映的指標。這樣,當乙個類需要根據一定的條件查詢乙個物件時,它會查詢本類物件,如果沒有找到,那麼會查詢基類,直到根基類。這類查詢包含windows訊息,命令,事...
從MFC訊息對映巨集分析MFC訊息對映的實現
在mfc中,我們可以找到如下三個巨集 declare massage map begine massage map class,bassclass end massage map 下面來分析這三個巨集 1 declare message map 作用 為乙個訊息響應類宣告必需的成員變數和成員函式。d...