1、#include指令??
包含指定的文件??
2、#define指令???
預(yù)定義,通常用它來(lái)定義常量(包括無(wú)參量與帶參量),以及用來(lái)實(shí)現(xiàn)那些“表面似和善、背后一長(zhǎng)串”的宏,它本身并不在編譯過(guò)程中進(jìn)行,而是在這之前(預(yù)處理過(guò)程)就已經(jīng)完成了
3、#typedef指令
常用來(lái)定義一個(gè)標(biāo)識(shí)符及關(guān)鍵字的別名它是語(yǔ)言編譯過(guò)程的一部分,但它并不實(shí)際分配內(nèi)存空間。
4、#ifndef?? #else?? #endif指令??
條件編譯。一般情況下,源程序中所有的行都參加編譯。但是有時(shí)希望對(duì)其中一部分內(nèi)容只在滿足一定條件才進(jìn)行編譯,也就是對(duì)一部分內(nèi)容指定編譯的條件,這就是“條件編譯”。有時(shí),希望當(dāng)滿足某條件時(shí)對(duì)一組語(yǔ)句進(jìn)行編譯,而當(dāng)條件不滿足時(shí)則編譯另一組語(yǔ)句。??
條件編譯命令最常見(jiàn)的形式為:??
#ifdef 標(biāo)識(shí)符??
?? 程序段1
#else
?? 程序段2??
#endif??
它的作用是:當(dāng)標(biāo)識(shí)符已經(jīng)被定義過(guò)(一般是用#define命令定義),則對(duì)程序段1進(jìn)行編譯,否則編譯程序段2。
5、#Pragma 指令??
在所有的預(yù)處理指令中,#Pragma 指令可能是最復(fù)雜的了,它的作用是設(shè)定編譯器的狀態(tài)或者是指示編譯器完成一些特定的動(dòng)作。其格式一般為??
#Pragma Para??
其中Para 為參數(shù),下面來(lái)看一些常用的參數(shù)。
l????????? message 參數(shù)。它能夠在編譯信息輸出窗口中輸出相應(yīng)的信息,這對(duì)于源代碼信息的控制是非常重要的。其使用方法為:??
#Pragma message(“消息文本”)??
當(dāng)編譯器遇到這條指令時(shí)就在編譯輸出窗口中將消息文本打印出來(lái)。??
當(dāng)我們?cè)诔绦蛑卸x了許多宏來(lái)控制源代碼版本的時(shí)候,我們自己有可能都會(huì)忘記有沒(méi)有正確的設(shè)置這些宏,此時(shí)我們可以用這條指令在編譯的時(shí)候就進(jìn)行檢查。假設(shè)我們希望判斷自己有沒(méi)有在源代碼的什么地方定義了_X86這個(gè)宏可以用下面的方法
#ifdef _X86
???????? #Pragma message(“_X86 macro activated!”)
???????? #endif???
當(dāng)我們定義了_X86這個(gè)宏以后,應(yīng)用程序在編譯時(shí)就會(huì)在編譯輸出窗口里顯示“_X86 macro activated!”。我們就不會(huì)因?yàn)椴挥浀米约憾x的一些特定的宏而抓耳撓腮了??
l????????? 另一個(gè)使用得比較多的pragma參數(shù)是code_seg。格式如:
#pragma code_seg( ["section-name"[,"section-class"] ] )??
它能夠設(shè)置程序中函數(shù)代碼存放的代碼段,當(dāng)我們開(kāi)發(fā)驅(qū)動(dòng)程序的時(shí)候就會(huì)使用到它。??
l????????? #pragma once??
只要在頭文件的最開(kāi)始加入這條指令就能夠保證頭文件被編譯一次,這條指令實(shí)際上在VC6中就已經(jīng)有了,但是考慮到兼容性并沒(méi)有太多的使用它。??
l????????? #pragma hdrstop??
表示預(yù)編譯頭文件到此為止,后面的頭文件不進(jìn)行預(yù)編譯。BCB可以預(yù)編譯頭文件以加快鏈接的速度,但如果所有頭文件都進(jìn)行預(yù)編譯又可能占太多磁盤(pán)空間,所 以使用這個(gè)選項(xiàng)排除一些頭文件。有時(shí)單元之間有依賴(lài)關(guān)系,比如單元A依賴(lài)單元B,所以單元B要先于單元A編譯。你可以用#pragma startup指 定編譯優(yōu)先級(jí),如果使用了#pragma package(smart_init) ,BCB就會(huì)根據(jù)優(yōu)先級(jí)的大小先后編譯。??
l????????? #pragma resource "*.dfm"??
表示把*.dfm文件中的資源加入工程。*.dfm中包括窗體外觀的定義。??
l????????? #pragma warning( disable : 4507 34; once : 4385; error : 164 )
等價(jià)于:??
#pragma warning(disable:4507 34) // 不顯示4507和34號(hào)警告信息
???????? #pragma warning(once:4385) // 4385號(hào)警告信息僅報(bào)告一次
???????? #pragma warning(error:164) // 把164號(hào)警告信息作為一個(gè)錯(cuò)誤。
同時(shí)這個(gè)pragma warning 也支持如下格式:
#pragma warning( push [ ,n ] )
#pragma warning( pop )
這里n代表一個(gè)警告等級(jí)(1---4)。
#pragma warning( push )保存所有警告信息的現(xiàn)有的警告狀態(tài)。
#pragma warning( push, n)保存所有警告信息的現(xiàn)有的警告狀態(tài),并且把全局警告
等級(jí)設(shè)定為n。
#pragma warning( pop )向棧中彈出最后一個(gè)警告信息,在入棧和出棧之間所作的
一切改動(dòng)取消。例如:
#pragma warning( push )
#pragma warning( disable : 4705 )
#pragma warning( disable : 4706 )
#pragma warning( disable : 4707 )
//.......
#pragma warning( pop )
在這段代碼的最后,重新保存所有的警告信息(包括4705,4706和4707)。
l????????? pragma comment(...)
該指令將一個(gè)注釋記錄放入一個(gè)對(duì)象文件或可執(zhí)行文件中。
常用的lib關(guān)鍵字,可以幫我們連入一個(gè)庫(kù)文件。
每個(gè)編譯程序可以用#pragma指令激活或終止該編譯程序支持的一些編譯功能。例如,對(duì)循環(huán)優(yōu)化功能:
#pragma loop_opt(on) // 激活
#pragma loop_opt(off) // 終止
有時(shí),程序中會(huì)有些函數(shù)會(huì)使編譯器發(fā)出你熟知而想忽略的警告,如“Parameter xxx is never used in function xxx”,可以這樣:
#pragma warn —100 // Turn off the warning message for warning #100
int insert_record(REC *r)
{ /* function body */ }
#pragma warn +100 // Turn the warning message for warning #100 back on
函數(shù)會(huì)產(chǎn)生一條有唯一特征碼100的警告信息,如此可暫時(shí)終止該警告。
每個(gè)編譯器對(duì)#pragma的實(shí)現(xiàn)不同,在一個(gè)編譯器中有效在別的編譯器中幾乎無(wú)效。可從編譯器的文檔中查看。
6、宏:__LINE__?? 和__FILE__
???? 定義源程序文件名和代碼行,這對(duì)于調(diào)試跟蹤代碼錯(cuò)誤行很有幫助。
__TIME__?????????? :編譯時(shí)間
__DATE__?????? :編譯日期
__TIMESTAMP__ :文件修改時(shí)間
7、調(diào)試宏:ASSERT()、VERIFY()、TRACE()
這三個(gè)宏在Debug環(huán)境下特別有效,常用于代碼的跟蹤調(diào)試。它們是否起作用取決于是否定義了預(yù)定義了宏 _DEBUG
l????????? ASSERT
ASSERT(booleanExpression)
說(shuō)明:
計(jì)算變量的值。如果結(jié)構(gòu)的值為0,那么此宏便打印一個(gè)診斷消息并且程序運(yùn)行失敗。如果條件為非0,那么什么也不做。診斷消息的形式為: assertion failed in file in line 其中name是元文件名,num是源文件中運(yùn)行失敗的中斷號(hào)。 在Release 版中,ASSERT不計(jì)算表達(dá)式的值也就不中斷程序。如果必須計(jì)算此表達(dá)式的值且不管環(huán)境如何那么用VERIFY代替ASSERT。
這個(gè)宏通常原來(lái)判斷程序中是否出現(xiàn)了明顯非法的數(shù)據(jù),如果出現(xiàn)了終止程序以免導(dǎo)致嚴(yán)重后果,同時(shí)也便于查找錯(cuò)誤。
ASSERT_VAILD
ASSERT_VAILD(pObject)
說(shuō)明:
用于檢測(cè)關(guān)于對(duì)象的內(nèi)部狀態(tài)的有效性。ASSERT_VALID調(diào)用此對(duì)象的AssertValid成員函數(shù)(把它們作為自己的變量來(lái)傳遞)。在 Release版中ASSERT_VALID什么也不做。在DEBUG版中,他檢查指針,以不同于NULL的方式進(jìn)行檢查,并調(diào)用對(duì)象自己的 AssertValid成員函數(shù)。如果這些檢測(cè)中有任何一個(gè)失敗的話,那么他會(huì)以與ASSERT相同的方法顯示一個(gè)警告的消息。
l????????? VERIFY
VERIFY(booleanExpression)
說(shuō)明:
在MFC的DEBUG版中,VERIFY宏計(jì)算它的變量值。如果結(jié)果為0,那么宏打印一個(gè)診斷消息并中止程序。如果條件不為0,那么什么工作也不作。診斷 有如下形式: assertion failed in file in line 其中name是源文件的名字,num是在源文件中失敗的中止行號(hào)。在 MFC的Release版中,VERIFY計(jì)算表達(dá)式值但不打印或中止程序。例如:如果表達(dá)式是個(gè)函數(shù)調(diào)用,那么調(diào)用成功。
l????????? TRACE
TRACE(exp)
說(shuō)明:
把一個(gè)格式化字符串送到轉(zhuǎn)儲(chǔ)設(shè)備,例如,文件或調(diào)試監(jiān)視器,功能上和printf相似,可以說(shuō)就是調(diào)試環(huán)境下printf的一個(gè)拷貝。TRACE宏是一個(gè) 在程序運(yùn)行時(shí)跟蹤變量值的方便形式。在DEBUG環(huán)境中,TRACE宏輸出到afxDump。在Release版中他不做任何工作。另外還有一組可以帶參 數(shù)的相似的宏:TRACE0、TRACE1、TRACE2和TRACE3。提供格式如:
TRACE0(exp)
TRACE1(exp,param1)
TRACE2(exp,param1,param2)
TRACE3(exp,param1,param2,param3)
與TRACE相似,但它把跟蹤字符串放在代碼段中,而不是DGROUP,因此使用少的DGROUP空間。這些宏的用法和printf類(lèi)似。
8、消息處理宏:DECLARE_MESSAGE_MAP 、BEGIN_MESSAGE_MAP、END_MESSAGE_MAP
DECLARE_MESSAGE_MAP()
說(shuō)明:
用戶程序中的每個(gè)CCmdTarget派生類(lèi)必須提供消息映射以處理消息。在類(lèi)定義的末尾使用DECLARE_MESSAGE_MAP宏。接著,在定義類(lèi) 成員函數(shù)的.CPP文件中,使用BEGIN_MESSAGE_MAP宏,每個(gè)用戶消息處理函數(shù)的宏項(xiàng)下面的列表以及END_MESSAGE_MAP宏。
注釋?zhuān)?
如果在DECLARE_MESSAGE_MAP之后定義任何一個(gè)成員,那么必須為他們指定一個(gè)新存取類(lèi)型(公共的,私有的,保護(hù)的)。
BEGIN_MESSAGE_MAP(the class,baseclass)
END_MESSAGE_MAP
說(shuō)明:
使用BEGIN_MESSAGE_MAP開(kāi)始用戶消息映射的定義。在定義用戶類(lèi)函數(shù)的工具(.cpp)文件中,以BEGIN_MESSAGE_MAP宏開(kāi)始消息映射,然后為每個(gè)消息處理函數(shù)增加宏項(xiàng),接著以END_MESSAGE_MAP宏完成消息映射。
9、消息映射宏:ON_COMMAND 、ON_CONTROL、ON_MESSAGE、ON_VBXEVENT、ON_Update_COMMAND_UI和ON_REGISTERED_MESSAGE
ON_COMMAND(id,memberFxn)
說(shuō)明:
此宏通過(guò)ClassWizard或手工插入一個(gè)消息映射。它表明那個(gè)函數(shù)將從一個(gè)命令用戶接口(例如一個(gè)菜單項(xiàng)或toolbar按鈕)處理一個(gè)命令消息。 當(dāng)一個(gè)命令對(duì)象通過(guò)指定的ID接受到一個(gè)Windows WM_COMMAND消息時(shí),ON_COMMAND將調(diào)用成員函數(shù)memberFxn處理此消 息。在用戶的消息映射中,對(duì)于每個(gè)菜單或加速器命令(必須被映射到一個(gè)消息處理函數(shù))應(yīng)該確實(shí)有一個(gè)ON_COMMAND宏語(yǔ)句。
ON_CONTROL(wNotifyCode,id,memberFxn)
說(shuō)明:
表明哪個(gè)函數(shù)將處理一個(gè)常規(guī)控制表示消息。控制標(biāo)識(shí)消息是那些從一個(gè)控制夫發(fā)送到母窗口的消息。
ON_MESSAGE(message,memberFxn)
說(shuō)明:
指明哪個(gè)函數(shù)將處理一用戶定義消息。用戶定義消息通常定義在WM_USER到0x7FF范圍內(nèi)。用戶定義消息是那些不是標(biāo)準(zhǔn) Windows WM_MESSAGE消息的任何消息。在用戶的消息映射中,每個(gè)必須被映射到一個(gè)消息處理函數(shù)。用戶定義消息應(yīng)該有一個(gè) ON_MESSAGE宏語(yǔ)句。
ON_Update_COMMAND_UI(id,memberFxn)
說(shuō)明:
此宏通常通過(guò)ClassWizard被插入一個(gè)消息映射,以指明哪個(gè)函數(shù)將處理一個(gè)用戶接口個(gè)更改命令消息。在用戶的消息映射中,每個(gè)用戶接口更改命令(比訊被映射到一個(gè)消息處理函數(shù))應(yīng)該有一個(gè)ON_Update_COMMAND_UI宏語(yǔ)句。
ON_VBXEVENT(wNotifyCode,memberFxn)
說(shuō)明:
此宏通常通過(guò)ClassWizard被插入一個(gè)消息映射,以指明哪個(gè)函數(shù)將處理一個(gè)來(lái)自VBX控制的消息。在用戶的消息映射中每個(gè)被映射到一消息處理函數(shù)的VBX控制消息應(yīng)該有一個(gè)宏語(yǔ)句。
ON_REGISTERED_MESSAGE(nmessageVarible,memberFxn)
說(shuō)明:
Windows的RegisterWindowsMesage函數(shù)用于定義一個(gè)新窗口消息,此消息保證在整個(gè)系統(tǒng)中是唯一的。此宏表明哪個(gè)函數(shù)處理已注冊(cè)消息。變量nMessageViable應(yīng)以NEAR修飾符來(lái)定義。
10、DEBUG_NEW
#define new DEBUG_NEW
說(shuō)明:
幫助查找內(nèi)存錯(cuò)誤。用戶在程序中使用DEBUG_NEW,用戶通常使用new運(yùn)算符來(lái)從堆上分配。在Debug模式下(但定義了一個(gè)DEBUG符號(hào)), DEBUG_NEW為它分配的每個(gè)對(duì)象記錄文件名和行號(hào)。然后,在用戶使用CMemoryState::DumpAllObjectSince成員函數(shù) 時(shí),每個(gè)以DEBUG_NEW分配的對(duì)象分配的地方顯示出文件名和行號(hào)。為了使用DEBUG_NEW,應(yīng)在用戶的資源文件中插入以下指令: #define new DEBUG_NEW 一旦用戶插入本指令,預(yù)處理程序?qū)⒃谑褂胣ew的地方插入DEBUG_NEW,而MFC作其余的工作。但 用戶編譯自己的程序的一個(gè)發(fā)行版時(shí),DEBUG_NEW便進(jìn)行簡(jiǎn)單的new操作,而且不產(chǎn)生文件名和行號(hào)消息。
11、異常宏:TRY、CATCH 、THROW、AND_CATCH、THROW_LAST和END_CATCH
TRY
說(shuō)明:
使用此宏建立一TRY塊。一個(gè)TRY識(shí)別一個(gè)可排除異常的代碼塊。這些異常在隨后的CATCH和AND_CATCH塊處理。傳遞是允許的:異常可以傳遞一個(gè)外部TRY塊,或者忽略它們或者使用THROW_LAST宏。
CATCH(exception_class,exception_object_pointer_name)
說(shuō)明:
使用此用定義一個(gè)代碼塊,此代碼用來(lái)獲取當(dāng)前TRY塊中都一個(gè)異常類(lèi)型。異常處理代碼可以訪問(wèn)異常對(duì)象,如何合適的話,就會(huì)得到關(guān)于異常的特殊原因的更多 消息。調(diào)用THROW_LAST宏以把處理過(guò)程一下一個(gè)外部異常框架,如果exception-class是類(lèi)CExceptioon,那么會(huì)獲取所有異 常類(lèi)型。用戶可以使用CObject::IsKindOf成員函數(shù)以確定那個(gè)特別異常被排除。一種獲取異常的最好方式是使用順序的AND_CATCH語(yǔ) 句,每個(gè)帶一個(gè)不同的異常類(lèi)型。此異常類(lèi)型的指針由宏定義,用戶不必定義。
注釋?zhuān)?
此CATCH塊被定義作一個(gè)C++范圍(由花括號(hào)描述)。如用戶在此范圍定義變量,那么它們只在吃范圍內(nèi)可以訪問(wèn)。他還可以用于異常對(duì)象的指針名。
THROW(exception_object_pointer)
說(shuō)明:
派出指定的異常。THROW中斷程序的運(yùn)行,把控制傳遞給用戶程序中的相關(guān)的CATCH塊。如果用戶沒(méi)有提供CATCH塊,那么控制被傳遞到一個(gè)MFC模塊,他打印出一個(gè)錯(cuò)誤并終止運(yùn)行。
AND_CATCH(exception_class,exception _object_point_name)
說(shuō)明:
定義一個(gè)代碼塊,它用于獲取廢除當(dāng)前TRY塊中的附加異常類(lèi)型。使用CATCH宏以獲得一個(gè)異常類(lèi)型,然后使用AND_CATCH宏獲得隨后的異常處理代 碼可以訪問(wèn)異常對(duì)象(若合適的話)已得到關(guān)于異常的特別原因的更多消息。在AND_CATCH塊中調(diào)用THROW_LAST宏以便把處理過(guò)程移到下個(gè)外部 異常框架。AND_CATCH可標(biāo)記CATCH或AND_CATCH塊的末尾。
注釋?zhuān)?
AND_CATCH塊被定義成為一個(gè)C++作用域(由花括號(hào)來(lái)描述)。若用戶在此作用域定義變量,那么記住他們只在此作用域中可以訪問(wèn)。他也用于exception_object_pointer_name變量。
THROW_LAST()
說(shuō)明:
此宏允許用戶派出一個(gè)局部建立的異常。如果用戶試圖排除一個(gè)剛發(fā)現(xiàn)的異常,那么一般此異常將溢出并被刪除。使用THROW_LAST,此異常被直接傳送到下一個(gè)CATCH處理程序。
END_CATCH
說(shuō)明:
標(biāo)識(shí)最后的CATCH或AND_CATCH塊的末尾。
12、DECLARE_DYNAMIC 、IMPLEMENT_DYNAMIC
DECLARE_DYNAMIC(class_name)
說(shuō)明:
但從CObject派生一個(gè)類(lèi)時(shí),此宏增加關(guān)于一個(gè)對(duì)象類(lèi)的訪問(wèn)運(yùn)行時(shí)間功能。把DECLARE_DYNAMIC宏加入類(lèi)的頭文件中,然后在全部需要訪問(wèn) 此類(lèi)對(duì)象的.CPP文件中都包含此模塊。如果像所描述那樣使用DELCARE_DYNAMIC和IMPLEMENT_DYNAMIC宏,那么用戶便可使用 RUNTIME_CLASS宏和CObject::IsKindOf函數(shù)以在運(yùn)行時(shí)間決定對(duì)象類(lèi)。如果DECLARE_DYNAMIC包含在類(lèi)定義中,那 么IMPLEMETN_DYNAMIC必須包含在類(lèi)工具中。??
IMPLEMENT_DYNAMIC(class_name,base_class_name)
說(shuō)明:
通過(guò)運(yùn)行時(shí)在串行結(jié)構(gòu)中為動(dòng)態(tài)CObject派生類(lèi)訪問(wèn)類(lèi)名和位置來(lái)產(chǎn)生必要的C++代碼。在.CPP文件中使用IMPLEMENT_DYNAMIC宏,接著一次鏈接結(jié)果對(duì)象代碼
13、DECLARE_DYNCreate、IMPLEMENT_DYNCreate
DECLARE_DYNCreate(class_name)
說(shuō)明:
使用DECLARE_DYNCRETE宏以便允許CObject派生類(lèi)的對(duì)象在運(yùn)行時(shí)刻自動(dòng)建立。使用此功能自動(dòng)建立新對(duì)象,例如,但它在串行化過(guò)程中從 磁盤(pán)讀一個(gè)對(duì)象時(shí),文件及視圖和框架窗應(yīng)該支持動(dòng)態(tài)建立,因?yàn)榭蚣苄枰詣?dòng)建立它。把DECLARE_DYNCreate宏加入類(lèi)的.H文件中,然后在全 部需要訪問(wèn)此類(lèi)對(duì)象的.CPP文件中包含這一模式。如果DECLARE_DYNCreate包含在類(lèi)定義中,那么IMPLEMENT_DYNCreate 必須包含在類(lèi)工具中。
IMPLEMENT_DYNCreate(class_name,base_class_name)
說(shuō)明:
通過(guò)DECLARE_DYNCreate宏來(lái)使用IMPLEMENT_DYNCreate宏,以允許CObject派生類(lèi)對(duì)象在運(yùn)行時(shí)自動(dòng)建立。主機(jī)使用 此功能自動(dòng)建立對(duì)象,例如,但它在串行化過(guò)程中從磁盤(pán)讀去一個(gè)對(duì)象時(shí),他在類(lèi)工具里加入IMPLEMENT_DYNCreate宏。若用戶使用 DECLARE_DYNCreate和IMPLEMENT_DYNCreate宏,那么接著使用RUNTIME_CLASS宏和CObject:: IsKindOf成員函數(shù)以在運(yùn)行時(shí)確定對(duì)象類(lèi)。若declare_dyncreate包含在定義中,那么IMPLEMENT_DYNCreate必須包 含在類(lèi)工具中。
14、DECLARE_SERIAL、IMPLEMENT_SERIAL
DECLARE_SERIAL(class_name)
說(shuō)明:
DECLARE_SERIAL為一個(gè)可以串行化的CObject派生類(lèi)產(chǎn)生必要的C++標(biāo)題代碼。串行化是把某個(gè)對(duì)象的內(nèi)容從一個(gè)文件讀出和寫(xiě)入一文件。 在.H文件中使用DECLARE_SERIAL宏,接著在需要訪問(wèn)此類(lèi)對(duì)象的全部.CPP文件中包含此文件。如果DECLARE_SERIAL包含在類(lèi)定 義中,那么IMPLEMENT_SERIAL必須包含在類(lèi)工具中。DECLARE_SERIAL宏包含全部DECLARE_DYNAMIC, IMPLEMENT_DYCreate的功能。
IMPLEMENT_SERIAL(class_name,base_class_name,wSchema)
說(shuō)明:
通過(guò)運(yùn)行時(shí)在串行結(jié)構(gòu)中動(dòng)態(tài)CObject派生類(lèi)訪問(wèn)類(lèi)名和位置來(lái)建立必要的C++代碼。在.CPP文件中使用IMPLEMENT_SERIAL宏,然后一次鏈接結(jié)果對(duì)象代碼。
15、RUNTIME_CLASS
RUNTIME_CLASS(class_name)
說(shuō)明:
使用此宏從c++類(lèi)名中獲取運(yùn)行時(shí)類(lèi)結(jié)構(gòu)。RUNTIME_CLASS為由class_name指定的類(lèi)返回一個(gè)指針到CRuntimeClass結(jié)構(gòu)。 只有以DECLARE_DYNAMIC、DECLARE_DYNCreate或DECLARE_SERIAL定義的CObject派生類(lèi)才返回到一個(gè) CRuntimeClass結(jié)構(gòu)的指針。