如果MFC的訊息對映表需要排序

2022-03-06 08:26:41 字數 992 閱讀 4047

這是今天下班前和同事討論的問題。

mfc的訊息對映通過幾個簡單的巨集,對windows的訊息機制做了非常好的物件導向封裝,一時為無數c++程式設計師所模仿(當然,mfc可能也是模仿別人的)。熟悉mfc訊息對映機制的人都知道,其本質無非就是把訊息和其處理函式放到乙個陣列當中,當程式接收到某訊息時,就會遍歷該陣列,查詢對應的訊息id,找到了就呼叫其處理函式,找不到就往其基類的陣列當中去找。

對,是線性查詢!那麼為什麼mfc沒有將訊息陣列排序,然後用二分查詢,把複雜度從o(n)提高到o(lg n)呢?原因我想可能是沒有必要,可以想像,乙個類中的訊息處理函式的個數是十分有限的,假設有100個訊息,最壞情況也就是比較100個整數,其效率影響也是非常小的。而為了這不必要的效率在framework級別加入排序與二分查詢的演算法,無疑增加了不必要的**複雜度。

那麼假設現在讓你實現對訊息對映表的排序,該如何來做呢?

另外乙個想法是在接收到乙個訊息之後,但在dispatch之前對訊息對映表進行排序,這個地點就是ccmdtarget::oncmdmsg,這是個好方法,只需對用到的那個類進行排序,有點lazy evaluation的味道。 但是我們不能每次呼叫都排序一遍,那就勢必需要乙個static的變數來標誌該訊息對映表是否有序,可以這麼做,在message map的巨集實現中,額外插入乙個初始值為false的static bool變數,和乙個sort的虛函式用來對訊息對映表進行排序(呼叫乙個公用的排序函式),並設定標誌位,這樣在ccmdtarget::oncmdmsg呼叫該sort虛函式就完成了排序。但這樣有個缺點,就是每個類都多了乙個額外的虛函式,對size和performance都有些影響。其實我們還可以復用訊息對映表來儲存這個標誌位 - 因為每個類都會對應乙個訊息對映表,所以只要在每個類的訊息對映表的第一項插入是否有序的標誌,在ccmdtarget::oncmdmsg中直接通過getmessagemap虛函式拿到當前類的訊息對映表,檢驗第一項標誌位是否為排序,如果為否則排序,否則繼續,句號。當然,這裡有一點要注意的是把訊息對映表的第一項挪做他用了,framework的其他地方不會誤解而當做普通項來使用。

MFC 訊息對映表 及 相關巨集定義

mfc 中通過通過不同於sdk的switch的方法來處理windows訊息,由訊息對映表 message map 和虛函式多型來處理指定的窗體訊息 宣告乙個訊息對映表 message map 在能處理訊息的類中中新增巨集 declare message map 注 深入淺出 mfc中有更詳盡系統的概...

MFC 訊息對映表 及 相關巨集定義

mfc相關技術說明 可參閱msdn mfc tno 5 mfc 中通過通過不同於sdk的switch的方法來處理windows訊息,由訊息對映表 message map 和虛函式多型來處理指定的窗體訊息 宣告乙個訊息對映表 message map 在能處理訊息的類中中新增巨集 declare mes...

MFC為何使用訊息對映表而不用虛函式?

這個問題是windows開發面試中最經常問到得問題,也是很有深度的乙個問題。有兩個帖子對該問題討論的比較深刻 說法一 虛函式實現占用記憶體較大 結論,該說法不靠譜!說法三 為了未來的可擴充套件性。相容新的系統級的訊息。我不是很清楚ms設計訊息對映的初衷,但是感覺它著眼點更側重於增加新訊息很容易,而不...