MFC 宏常识
1、宏就是用宏定義指令#define定義一個標(biāo)識符,用它來表示一個字符串或一段源代碼。
MFC宏作為MFC類庫的一個組成部分在MFC應(yīng)用程序中經(jīng)常出現(xiàn)。
MFC宏在路徑
".../Microsoft Visual Studio/VC/atlmfc/include"下的Afxwin.h、Afx.h及Afxmsg_.h等MFC頭文件中分別進(jìn)行了定義。
(1)常用的MFC宏
包括消息映射宏、運(yùn)行時類型識別宏、序列化宏、調(diào)試宏和異常宏等。
要想真正了解MFC的內(nèi)部機(jī)制和熟練運(yùn)用MFC,必須掌握MFC宏的基本原理和使用方法。
(2)有關(guān)運(yùn)行時類型識別的宏
運(yùn)行時類型識別(RTTI)是指在程序運(yùn)行時能夠確定一個對象的類型。
MFC擴(kuò)充了一般C++中運(yùn)行時類型識別的功能,當(dāng)一個類支持MFC的運(yùn)行時類型識別功能時,它允許程序獲取對象的信息(如類名、所占存儲空間大小及版本號等)和基類信息(RTCI)。
?
1.運(yùn)行時基礎(chǔ)宏:RUNTIME_CLASS(class_name)
返回參數(shù)class_name所指定類的靜態(tài)成員變量class##class_name的指針,該指針指向一個CRuntime結(jié)構(gòu)。
宏定義如下:
#define RUNTIME_CLASS(class_name) ((CRuntimeClass*)(&class_name::class##class_name))?
程序能夠利用RUNTIME_CLASS宏實時創(chuàng)建類的實例。
為了讓這個宏起作用,定義的類必須是類CObject的派生類,并且在派生類的定義中必須使用宏DECLARE_DYNAMIC、DECLARE_DYNCREATE或DECLARE_SERIAL,
在派生類的實現(xiàn)源文件中使用宏IMPLEMENT_DYNAMIC、IMPLEMENT_DYNCREATE或IMPLEMENT_SERIAL。
這三個宏使MFC類及其派生類具有三個不同等級的功能。
?
2.動態(tài)支持宏:DECLARE_DYNAMIC(class_name)和IMPELMENT_DYNAMIC(class_name,base_class_name)
使用動態(tài)支持宏能夠使CObject派生類的對象具有基本的類型識別機(jī)能,可以通過調(diào)用成員函數(shù)CObject::IsKindOf(ClassName)測試對象與給定類Class_Name的關(guān)系。
DECLARE_DYNAMIC()宏定義如下:
#define DECLARE_DYNAMIC(class_name) \ public: \ static const CRuntimeClass class##class_name; \ virtual CRuntimeClass* GetRuntimeClass() const; \例1: 定義一個類MyClass,使用RUNTIME_CLASS()宏的基本對象識別功能
//在頭文件MyClass.h class CMyClass:public CObject { DECLARE_DYNAMIC(CMyClass) public: void someFunction(void); };//在實現(xiàn)源文件MyClass.cpp中 #include "MyClass.h" IMPLEMENT_DYNAMIC(CMyClass,CObject) void CMyClass::SomeFunction(void) { CObject* pObject=new CMyClass; if(pObject->IsKindOf(RUNTIME_CLASS(CMyClass))) { CMyClass* pMyObject=(CMyClass*)pObject; AfxMessageBox("MyObject is an object of the class CMyClass"); } else AfxMessageBox("MyObject is not an object of the class CMyClass"); delete pObject; }?
3.動態(tài)創(chuàng)建宏:DECLARE_DYNCREATE(class_name)和 IMPLEMENT_DYNCREATE(class_name,base_class_name)
動態(tài)創(chuàng)建是動態(tài)支持的一個超集,除了基本的類型識別機(jī)能,使用動態(tài)創(chuàng)建宏能夠使CObject類的派生類具有運(yùn)行時動態(tài)創(chuàng)建對象的功能。
注意,支持動態(tài)創(chuàng)建的類必須有一個默認(rèn)的不帶參數(shù)的構(gòu)造函數(shù),用于一個穩(wěn)定的對象。
MFC應(yīng)用程序框架利用這個機(jī)能動態(tài)創(chuàng)建新的對象。
?
例如,當(dāng)序列化期間從磁盤讀取一個對象時,應(yīng)用程序框架將利用文檔類、視圖類和框類的動態(tài)創(chuàng)建功能業(yè)動態(tài)創(chuàng)建它們的運(yùn)行時對象。
在MFC應(yīng)用程序框架中,向?qū)镸FC派生類自動添加了這兩個動態(tài)創(chuàng)建宏。
?
4.序列化:DECLARE_SERIAL()和IMPLEMENT_SERIAL()
序列化是動態(tài)支持和動態(tài)創(chuàng)建的一個超集,除了基本的類別識別和動態(tài)創(chuàng)建機(jī)能,使用序列化宏能夠使CObject類的派生類具有實現(xiàn)對象持久性的序列化功能。
MFC調(diào)試宏
1.TRACE跟蹤聲明宏
??? TRACE()宏語法說明如下:
TRACE(<輸出格式>,<表達(dá)式>)其中的參數(shù)是由輸出格式和表達(dá)式組成,其形式與函數(shù)printf()的參數(shù)一樣。
TRACE宏的功能是在調(diào)試運(yùn)行時把表達(dá)式的值輸出到Output調(diào)試窗口。
TRACE宏只在MFC應(yīng)用程序Debug版的調(diào)試運(yùn)行狀態(tài)下才起作用,并且必須保證在Developer Studio中的Enable tracing設(shè)置,這需要執(zhí)行Tools|MFC Tracer命令。
?
例2 對于以下代碼:
char* szName="LiMing"; int nAge=18; TRACE("Name=%s,Age=%",szName,nAge); 調(diào)試運(yùn)行時在Ouput窗口將輸出以下內(nèi)容:Name=LiMing,Age=18?
2.ASSERT斷言宏?
ASSERT(<表達(dá)式>)當(dāng)執(zhí)行該宏時,如果表達(dá)式為真,則程序繼續(xù)執(zhí)行;否則暫停程序的運(yùn)行,并彈出一個對話框,告訴用戶程序暫停運(yùn)行的行及所在文件的信息。用戶可選擇終止運(yùn)行、調(diào)試程序或繼續(xù)運(yùn)行。
例如,在視圖派生類的成員函數(shù)GetDocument()中,MFC使用了ASSERT()宏判斷當(dāng)前文檔是否是運(yùn)行時類的對象。
?? 例3 :設(shè)已自定義一個名為CMyFrame的框架窗口類,它也是CFrameWnd的派生類。在程序中構(gòu)建一個與CMyFrame相關(guān)聯(lián)的文檔模板對象,并為構(gòu)建的文檔模板創(chuàng)建框架窗口。然后可以編寫如下代碼使用這個框架窗口。
CMyFrame* pFrame=(CMyFrame*)AfxGetMainWnd(); ASSERT(pFrame->IsKindOf(RUNTIME_CLASS(CMyFrame))); //判斷pFrame的類型 pFrame->DoSomeOperation(); //調(diào)用成員函數(shù)完成某些操作AfxGetMainWnd()是一個全局函數(shù),返回值向應(yīng)用程序主窗口的指針,類型為CWnd*,因此必須對它進(jìn)行強(qiáng)制類型轉(zhuǎn)換。但如何知道是否轉(zhuǎn)換成功?
CMyFrame類也是CObject的派生類,可以結(jié)合成員函數(shù)IsKindOf()使用ASSERT()宏來檢查pFrame的類型。
在pFrame->DoSomeOperation()語句之前插入ASSERT()宏,就可以在運(yùn)行機(jī)制時做類型檢查,當(dāng)類型不匹配時,引發(fā)一個斷方,可以中斷程序執(zhí)行。
ASSERT宏只在Debug版本中才起作用,它在Release版本中是不會被編譯的,
?
在Release版本中可以使用VERIFY宏。VERIFY宏與ASSERT宏在Debug版本中的作用一致,
區(qū)別在于在Release版本中VERIFY宏仍然有效,它會對參數(shù)表達(dá)式求值,但不管結(jié)果如何都不會暫停程序的運(yùn)行。
為了避免給程序帶來不良的后果,使用ASSERT宏時必須保證參數(shù)表達(dá)式中不能有函數(shù)調(diào)用語句,
因為ASSERT宏中的函數(shù)調(diào)用語句在Release版本中根本不在。
出現(xiàn)這種情況時,可以使用VERIFY宏取代ASSERT宏。
?
3.ASSERT_VALID斷言有效宏
ASSERT_VALID()宏語法說明如下:
ASSERT_VALID(<指針>)ASSERT_VALID宏用于檢查指針和對象的有效性。對于一般指針,只檢查指針是否為空。
對于MFC類對象指針,通過調(diào)用CObject類的成員函數(shù)AssertValid()判斷對象的舍法性。
ASSERT_VALID宏提示指針或?qū)ο鬅o效的方式與ASSERT宏一樣,彈出一個信息對話框。
ASSERT_VALID宏也是只在Debug版本中才起作用。
總結(jié)
- 上一篇: c语言本身有输入输出语句正确错误,C语言
- 下一篇: Window 窗口层次关系