本文整理自侯捷老師的著作「深入淺出 MFC」。
MFC 六大關鍵技術:
1. MFC 程式初始過程
2. RTTI(Runtime Type Information)
3. Dynamic Creation
4. Persistence
5. Message Mapping
6. Message Routing
============================================================
【MFC 程式初始過程】
1. 存在一個全域類別物件 theApp,首先呼叫其類別建構函式。
2. 呼叫 main function。由 MFC 替我們呼叫,因此程式中看不見 main function。
AfxWinMain() {
AfxWinInit(); // will call AfxInitThread()
theApp -> InitApplication(); // MFC 內部管理,和 Document Template & CDocManager 有關
theApp -> InitInstance(); // register, create, show, update window
theApp -> Run(); // 訊息迴路
}
============================================================
【RTTI(Runtime Type Information)】
在執行時期,偵測某個物件是否屬於「某種類別」,並回傳 TRUE 或 FALSE。
舉例來說:
CSquare *pSquare = new CSquare;
cout << pSquare -> IsKindOf ( CSquare ); // TRUE
cout << pSquare -> IsKindOf ( CRect); // TRUE
cout << pSquare -> IsKindOf ( CShape); // TRUE
cout << pSquare -> IsKindOf ( CCircle ); // FALSE
為了達到 RTTI 的能力,我們在建構類別時,記錄必要的資訊以便建立型錄。
型錄中的類別資訊,可以用 linked list 串接起來,將來方便一一比對。
我們將這份「類別型錄」的串列元素,稱為「CRuntimeClass」。
為什麼需要 RTTI?
因為 RTTI 可以提供各種應用,例如解決棘手的動態生成問題。
============================================================
【Dynamic Creation】
存放在 ram 裡資料,生命受到電力左右,無法永續留存。
因此,我們可以將資料寫進檔案。
寫進檔案的資料,可能是某個物件的成員變數。
因此將資料從檔案讀出後,必須依據檔案上的記載,new 出此物件。
問題在於,檔案中只有記載類別名稱,而沒有類別型態。
舉例來說:
char className[30] = getClassName(); // 從檔案(或使用者輸入)取得一個類別名稱
CObject *obj = new classname; // 這裡行不通
在 new classname 這個動作將會失敗。即使成功,new 出來的物件究竟該是什麼類別型態?
一個指向 MFC 類別老祖宗 CObject 的物件指標,雖然一定可以容納,但未必能滿足程式需求。
透過 RTTI 則可以解決此問題。
如果我們將類別的大小以及建構函式,皆記錄在類別型錄中,
程式在執行時期獲得一個類別名稱,便可在類別型錄找出對應元素,
呼叫其建構函式,產生物件。
疑問:但,最當初為何不將類別型態一同寫進檔案?
============================================================
【Persistence】
Persistence 為物件導向的術語,意思是「把物件永久保留下來」。
如何做到?
將資料寫入檔案。
在 Document / View 的架構中,資料都放在一份 document 裡面。
若資料為物件,我們會先記載其類別名稱,接著記載物件中的資料。
讀檔時,利用 dynamic creation,重新產生類別名稱所對應的物件。
透過 Serialize 控制檔案的讀寫。
每個類別都應該有自己的 Serialize 函式。
為了達到 Persistence,我們需要 Dynamic Creation。
為了達到 Dynamic Creation,我們需要 RTTI。
============================================================
【Message Mapping】
規劃一個訊息流動網。
利用訊息映射表格,讓程式更模組化。
BEGIN_MESSAGE_MAP()
ON_COMMAND()
END_MESSAGE_MAP()
實做的觀念,舉例來說:
struct MSGMAP_ENTRY messageEntries[] = {
WM_CREATE, OnCreate,
WM_PAINT, OnPaint,
WM_SIZE, OnSize,
…
};
CALLBACK WndProc() {
for ( i=0; i < dim(messageEntries); ++i) {
if (message == messageEntries[i].nMessage)
return (messageEntries[i].pfn)(hWnd, message, wParam, lParam);
}
}
============================================================
【Message Routing】
有了訊息流動網,,當收到訊息時,指示此訊息該流向何處,就像是 WndProc()。
http://www.wretch.cc/blog/bafu/13708333
- May 30 Mon 2011 16:33
[C++] MFC 六大關鍵技術
全站熱搜
留言列表