最近看侯捷的MFC深入淺出,簡單總結一下。
第一章首先就是先了解一下windows程序設計的基礎知識,包括win32程序開發基礎,什么*.lib,*.h,*.cpp的,程序入口點WinMain函數,窗口注冊,消息循環,消息映射等。還有控制台(console)應用程序的運行過程以及與MFC的區別,進程與線程的誕生(CreatProcess()、CreateThread()、_beginthread()等)與消亡(ExitProcess()、endthread()等)。
第二章講解了一些C++的重要性質,有this指針的使用,虛函數與多態,靜態成員(函數與變量),執行時識別(RTTI),動態生成(Dynamic Creation),異常處理(Exception Handling),模板(Template)等。
虛函數的總結:
1 、 父類指針指向子類對象時,該指針只能引用父類的方法。
2 、子類指針指向父類對象時,問題多多,需要強制轉換,不符合實際。
3 、父類和子類有同名成員函數時,父類指針永遠只能調用父類方法而無論其指向是父類還是子類,子類指針也類似。
如果你預期衍生類別有可能重新定義某一個成員函數,那么你就在基礎類別中把此函數設為virtual。
四種不同對象的生存方式:(in stack ,in heap,global,local static)
1 void Func() 2 { 3 CObject ob;//在堆棧(stack)中產生ob對象 4 } 5 void Func() 6 { 7 CObject *ob = new CObject();//在堆(heap)中產生ob對象 8 } 9 CObject ob;//全局對象 10 void Func() 11 { 12 static CObject ob;//局部靜態對象,產生在固定的內存上(但是它既不是stack,也不是heap) 13 }
其中靜態全局對象的構造必須依靠startup碼實現,startup碼是更早於程序進入點(main or WinMain)執行的代碼,有C++編譯器提供。
模板總結
1、模板函數
例子:
template <class T>
T power(T base, int exponent);
其中的class不是C++中的class,這里它只是指一個普通的數據類型,而T就是一種具體的數據類型,且只有在調用函數時才確定T的值。宏觀上說T可以是任何類型的數據類型,前提是函數內的操作合法,編譯器能識別出。
2、類模板
類的聲明比較簡單,比一般的類聲明多了一行 template <class T>
1 template <class T> //聲明 2 class CTest 3 { 4 public : 5 CTest(T t1, T t2, T t3); 6 T Min(); 7 T Max(); 8 private: 9 T a, b, c; 10 };
函數的定義如下,規則就是:每一個成員函數前都要加上template <class T>,而且類別名稱應該使用CTest<T>。
1 template <class T>//這個必須加上 2 T CTest<T>::Min() 3 { 4 T minab = a < b ? a : b; 5 return minab < c ? minab : c; 6 }
類的使用如下,必須首先指定類型
1 CTest<int> obj1(2, 5, 4); //int類型 2 cout << obj1.Min() << endl; 3 cout << obj1.Max() << endl; 4 5 CTest<float> obj1(2.23, -3.35, 9.334); //float類型 6 cout << obj1.Min() << endl; 7 cout << obj1.Max() << endl;
第三章介紹MFC的六大關鍵技術,包括MFC初始化、執行時類型識別(RTTI)、動態生成(Dynamic Creation)、永久保存(Persistence)、消息映射(Message Mapping)、命令繞行(Command Routing)。
1、MFC初始化----尋找main函數
C++規定,全局對象的構造將比main或WinMain函數更早。
首先是全局構造
CObject構造函數 -> CCmdTarget -> CWinThread -> CWinApp -> theApp構造函數
然后進入WinMain函數
WinMain -> AfxWinMain -> AfxWinInit -> theApp.InitApplication -> theApp.InitInstance
接着執行線程過程。
theApp.Run()
最后清理
AfxWinTerm
2、執行時類型識別(RTTI)-- -- 查詢父子關系(true or false)
CRuntimeClass的實現要通過幾個復雜的宏DECLARE_DYNAMIX(Cxxx)和IMPLEMENT_DYNAMIC(Cxxx,Cxxxbase),在類內部聲明這兩個宏,就可以將該類加入到類型識別庫。而CObject的函數IsKindOf()則可以指向任何派生至CObject的類,然后調用它就可以找到基類。
3、動態生成(Dynamic Creation) ----- 如何從文件中讀取一個類並實現它
動態生成也通過CRuntimeClass來實現,加入兩個成員變量,並通過宏來實現。DECLARE_DYNCREATE 和IMPLEMENT_DYNCREATE 。
4、永久保存(Persistence) -- -- 將對象寫入到文件(Serialize)
這需要用到宏DECLARE_SERIAL / IMPLEMENT_SERIAL,以及CObject的虛函數 virtual void Serialize(CArchive& ar);
5 、消息映射(Message Mapping)---- 消息如何獲取
宏DECLARE_MESSAGE_MAP / BEGIN_MESSAGE_MAP / END_MESSAGE_MAP
在WinMain函數里加入一死循環
1 while (GetMessage (&msg, NULL, 0, 0)) 2 { 3 TranslateMessage (&msg) ; 4 DispatchMessage (&msg) ; 5 }
6、命令繞行(Command Routing)---- 消息流動方向
一般Window消息(WM_xxx),一定是從子類流向父類,不可能旁流。
命令消息WM_COMMAND 的消息流向比較另類,可以橫向流動