本文整理自侯捷老師的著作「深入淺出 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

arrow
arrow
    全站熱搜

    天才R 發表在 痞客邦 留言(0) 人氣()