VC++訊息對映的思考 (轉)

amyz發表於2007-10-31
VC++訊息對映的思考 (轉)[@more@] 

VC++訊息對映的思考:namespace prefix = o ns = "urn:schemas--com::office" />

作者:to:haoqingxin@263">郝慶欣

在學習VC++的時候,大家都不可避免的用到訊息對映。我們都知道C++是一種面向的語言,VC++中為什麼這樣來實現訊息對映呢?
  首先要明白一個包含了訊息處理的是如何工作的。
  一般來說一個包含了訊息處理的Windows程式至少要包含兩個
   第一個:
    int WIN WinMain(
      HINSTANCE hInstance,   // handle to current instance
      HINSTANCE hPrevInstance,  // handle to previous instance
      LPSTR lpCmdLine,     // command line
      int nCmdShow     // show state
    );
   第二個:
   long FAR PASCAL WndProc(HWND hWnd, message,WORD wParam,LONG lParam);
   我們不必糾纏程式實現的細節,只要明白在第一個函式WinMain中要註冊WndProc函式,通俗一些的理解就是WinMain告訴Windows,聽著,我知道你要產生很多訊息,我這裡有一個WndProc函式負責處理你傳遞來的各種訊息。當然訊息的格式都是系統規定好的。

其次要明白C++中是如何實現多型性的。

我們知道多型性實現的關鍵是晚繫結(或者稱為後期繫結),其實質就是並沒有在編譯期間指定函式的絕對地址,而是指定了某個類內部該函式的偏移地址。

為了實現上面的功能,編譯器為我們作了手腳

1、  在每個帶有虛擬函式的類中,編譯器秘密放置了一個指標,稱為Vpointer

2、  當系統執行時,為每個類建立一個VTABLE,其中包含了可以呼叫虛擬函式地址。

3、  Vpointer出始化,指向VTABLE,透過在Vtable中偏移,來找到正確的需要呼叫的函式地址。

然後是MFC對Window API進行的封裝

當我們利用MFC開發程式的時候,尤其是開發介面應用程式的時候,必定要用到CWnd或者派生於CWnd的類。根據物件導向的設計原則,對於CWnd的一些通用函式,例如視窗大學改變(OnSize),視窗移動(OnMove),最好是在CWnd中宣告為虛擬函式,然後在繼承的類裡面過載他們。但是,這樣以來,每個相關的派生類都要有一個Vpointer和一套記錄Vtable,而CWnd中通用函式是如此至多,CWnd的派生類也很多,必然會導致系統在執行是佔用過多的資源(),這樣顯然是不合適的。

 

那麼MFC是如何實現的呢?

答案就是在CWnd基類中儘可能的少用虛擬函式,採用訊息對映機制來代替。

大家可以看一下CWnd的類中的函式,就會發現這一點。

CWnd::OnMove 

afx_msg void OnMove( int x, int y );

上面這個函式就不是虛擬函式。

 最後的問題訊息對映是如何實現的呢?

 用一句話說,就是利用宏定義來實現程式導向的訊息處理。

例如在VC中有如下的訊息對映宏。

BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)  //{{AFX_MSG_MAP(CMainFrame)

ON_WM_CREATE() 

//}}AFX_MSG_MAP

ON_COMMAND(ID_FONT_DROPDOWN, DoNothing)

END_MESSAGE_MAP()

經過編譯後,程式碼被替換為如下形式(這只是作講解,實際情況比這複雜得多):

//BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd) 

CMainFrame::newWndProc(...)

{

switch(...)

{

//{{AFX_MSG_MAP(CMainFrame)

// ON_WM_CREATE() 

case(WM_CREATE):

OnCreate(...);

break;

//}}AFX_MSG_MAP

// ON_COMMAND(ID_FONT_DROPDOWN, DoNothing)

case(WM_COMMAND):

if(HIWORD(wP)==ID_FONT_DROPDOWN)

{

DoNothing(...);

}

break;

//END_MESSAGE_MAP()

}

}

這樣,VC++就消除了對部分虛擬函式的需要,從而節省了記憶體空間。

 

參考資料:

  Thingking in C++,Bruce Eckel;

    聞怡洋

  寒巖之上,唯我獨行---小朱


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10752019/viewspace-979982/,如需轉載,請註明出處,否則將追究法律責任。

相關文章