MFC宏常識


1、宏就是用宏定義指令#define定義一個標識符,用它來表示一個字符串或一段源代碼。

MFC宏作為MFC類庫的一個組成部分在MFC應用程序中經常出現。

MFC宏在路徑

".../Microsoft Visual Studio/VC/atlmfc/include"

下的Afxwin.h、Afx.h及Afxmsg_.h等MFC頭文件中分別進行了定義。

(1)常用的MFC宏

包括消息映射宏運行時類型識別宏序列化宏調試宏異常宏等。

要想真正了解MFC的內部機制和熟練運用MFC,必須掌握MFC宏的基本原理和使用方法。

(2)有關運行時類型識別的宏

運行時類型識別(RTTI)是指在程序運行時能夠確定一個對象的類型。

MFC擴充了一般C++中運行時類型識別的功能,當一個類支持MFC的運行時類型識別功能時,它允許程序獲取對象的信息(如類名、所占存儲空間大小及版本號等)和基類信息(RTCI)。

 

1.運行時基礎宏:RUNTIME_CLASS(class_name)

返回參數class_name所指定類的靜態成員變量class##class_name的指針,該指針指向一個CRuntime結構。

宏定義如下:

#define RUNTIME_CLASS(class_name)  
              ((CRuntimeClass*)(&class_name::class##class_name)) 

 

程序能夠利用RUNTIME_CLASS宏實時創建類的實例。

為了讓這個宏起作用,定義的類必須是類CObject的派生類,並且在派生類的定義中必須使用宏DECLARE_DYNAMIC、DECLARE_DYNCREATE或DECLARE_SERIAL,

在派生類的實現源文件中使用宏IMPLEMENT_DYNAMIC、IMPLEMENT_DYNCREATE或IMPLEMENT_SERIAL。

這三個宏使MFC類及其派生類具有三個不同等級的功能。

 

2.動態支持宏:DECLARE_DYNAMIC(class_name)和IMPELMENT_DYNAMIC(class_name,base_class_name)

使用動態支持宏能夠使CObject派生類的對象具有基本的類型識別機能,可以通過調用成員函數CObject::IsKindOf(ClassName)測試對象與給定類Class_Name的關系。

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);  
};

//在實現源文件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.動態創建宏:DECLARE_DYNCREATE(class_name)和 IMPLEMENT_DYNCREATE(class_name,base_class_name)

動態創建是動態支持的一個超集,除了基本的類型識別機能,使用動態創建宏能夠使CObject類的派生類具有運行時動態創建對象的功能。

注意,支持動態創建的類必須有一個默認的不帶參數的構造函數,用於一個穩定的對象。

MFC應用程序框架利用這個機能動態創建新的對象。

 

例如,當序列化期間從磁盤讀取一個對象時,應用程序框架將利用文檔類、視圖類和框類的動態創建功能業動態創建它們的運行時對象。

在MFC應用程序框架中,向導為MFC派生類自動添加了這兩個動態創建宏。

 

4.序列化:DECLARE_SERIAL()和IMPLEMENT_SERIAL()

序列化是動態支持和動態創建的一個超集,除了基本的類別識別和動態創建機能,使用序列化宏能夠使CObject類的派生類具有實現對象持久性的序列化功能。


MFC調試宏

1.TRACE跟蹤聲明宏

    TRACE()宏語法說明如下:

TRACE(<輸出格式>,<表達式>)

其中的參數是由輸出格式和表達式組成,其形式與函數printf()的參數一樣。

TRACE宏的功能是在調試運行時把表達式的值輸出到Output調試窗口。

TRACE宏只在MFC應用程序Debug版的調試運行狀態下才起作用,並且必須保證在Developer Studio中的Enable tracing設置,這需要執行Tools|MFC Tracer命令。

 

例2 對於以下代碼:

    char* szName="LiMing";  

    int nAge=18;  

    TRACE("Name=%s,Age=%",szName,nAge); 

調試運行時在Ouput窗口將輸出以下內容:

      Name=LiMing,Age=18

 

2.ASSERT斷言宏 

 ASSERT(<表達式>)

當執行該宏時,如果表達式為真,則程序繼續執行;否則暫停程序的運行,並彈出一個對話框,告訴用戶程序暫停運行的行及所在文件的信息。用戶可選擇終止運行、調試程序或繼續運行。

例如,在視圖派生類的成員函數GetDocument()中,MFC使用了ASSERT()宏判斷當前文檔是否是運行時類的對象。

   例3 :設已自定義一個名為CMyFrame的框架窗口類,它也是CFrameWnd的派生類。在程序中構建一個與CMyFrame相關聯的文檔模板對象,並為構建的文檔模板創建框架窗口。然后可以編寫如下代碼使用這個框架窗口。

      CMyFrame* pFrame=(CMyFrame*)AfxGetMainWnd();  

      ASSERT(pFrame->IsKindOf(RUNTIME_CLASS(CMyFrame)));   //判斷pFrame的類型

      pFrame->DoSomeOperation();        //調用成員函數完成某些操作

AfxGetMainWnd()是一個全局函數,返回值向應用程序主窗口的指針,類型為CWnd*,因此必須對它進行強制類型轉換。但如何知道是否轉換成功?

CMyFrame類也是CObject的派生類,可以結合成員函數IsKindOf()使用ASSERT()宏來檢查pFrame的類型。

在pFrame->DoSomeOperation()語句之前插入ASSERT()宏,就可以在運行機制時做類型檢查,當類型不匹配時,引發一個斷方,可以中斷程序執行。

ASSERT宏只在Debug版本中才起作用,它在Release版本中是不會被編譯的,

 

在Release版本中可以使用VERIFY宏。VERIFY宏與ASSERT宏在Debug版本中的作用一致,

區別在於在Release版本中VERIFY宏仍然有效,它會對參數表達式求值,但不管結果如何都不會暫停程序的運行。

為了避免給程序帶來不良的后果,使用ASSERT宏時必須保證參數表達式中不能有函數調用語句,

因為ASSERT宏中的函數調用語句在Release版本中根本不在。

出現這種情況時,可以使用VERIFY宏取代ASSERT宏。

 

3.ASSERT_VALID斷言有效宏

ASSERT_VALID()宏語法說明如下:

ASSERT_VALID(<指針>)

ASSERT_VALID宏用於檢查指針和對象的有效性。對於一般指針,只檢查指針是否為空。

對於MFC類對象指針,通過調用CObject類的成員函數AssertValid()判斷對象的舍法性。

ASSERT_VALID宏提示指針或對象無效的方式與ASSERT宏一樣,彈出一個信息對話框。

ASSERT_VALID宏也是只在Debug版本中才起作用。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM