C/C++編程小技巧-宏的使用

近日無聊,奉獻一些宏編程技巧給大家。C++書裡絕對會千方百計地叫你別用宏而用inline函數取代它,這是給那些品德高尚的程序員的建議,沒人品的程序員都喜歡用宏,比如我:P 。哈哈,說笑的說笑的,宏確實是很好用的東西,只是對於那些未經過C洗禮過來的程序員,不太願意接受它,所以這裡就給大家介紹一些。

C/C++編程小技巧-宏的使用

1.我們經常使用枚舉,但是枚舉又經常和字符串打交道。也許你經常會將一個枚舉類型轉換成一個字符串類型。有的,在很多時候,比如文件的存取,日誌記入系統等。這裡介紹一種利用宏來轉換枚舉為字符串的方法。

#define PrintOut(x) case(x) : std::cout<

有了這個東西,你就可以很輕鬆地寫一些代碼比如

enum

{

JOHNNY = 0,

AYA,

KARAS,

HS2000

}

Switch(Somebody)

{

PrintOut(Johnny);break;

PrintOut(AYA);break;

PrintOut(KARAS);break;

PrintOut(HS2000);break;

}

2.有時我們很懶得寫類裡頭的GetXXX, SetXXX,這些東西千篇一律.這裡我在介紹大家一種懶惰的方法:

#define SET_ACCESSOR( x, y ) void Set##y( x t ) { m_##y = t; };

#define GET_ACCESSOR( x, y ) x Get##y() { return m_##y; } const;

#define GET_SET_ACCESSOR( x, y ) SET_ACCESSOR( x, y ) GET_ACCESSOR( x, y )

#define SETP_ACCESSOR( x, y ) void Set##y( x* t ) { m_##y = *t; };

#define GETP_ACCESSOR( x, y ) x* Get##y() { return &m_##y; } const;

#define GETP_SETP_ACCESSOR( x, y ) SETP_ACCESSOR( x, y ) GETP_ACCESSOR( x, y )

好啦,現在你可以拿著這個宏去偷懶啦,比如你有個類

class A

{

public:

A();

~A();

void SetData( int x ){ m_Data = x; };

int GetData(){ return m_Data; };

private:

int m_Data;

};

現在你這麼寫

class A

{

public:

A();

~A();

GET_SET_ACCESSOR( int, Data );

private:

int m_Data;

};

現在代碼變得簡潔了,一句話搞定,這個是絕對的懶人專用。

3.我們都喜歡用assert()來斷言,這是調試程序的有利武器。其實我們也可以自己寫assert或擴展原來的assert。這裡我需要告訴大家__asm{int 3}是一個讓調試器產生斷點的指令。也是assert的原理。

#ifdef _DEBUG

#define my_assert(x) if ((x) == false) __asm { int 3 }

#else

#define my_assert(x) {}

#endif

或者我們還可以寫

#define my_assert( exp,desc ) if( MyAssertFunc(exp,desc,__LINE__,__FILE__) ){ __asm{ int3 } }

4.我們也喜歡對new和delete做一些小動作(大動作就是調用operator new / delete)。所以我們可以這麼寫

#ifdef new

#undef new

#ifdef delete

#undef delete

#define new (log("new here"),false ) ? NULL : new

#define delete ( log("delete here"), false ) ? NULL : delete

好啦,現在你的new和delete具有日誌的功能啦。當然我更願意做進operator new / delete中。

5.以下是我寫程序時一定會加上的宏。雖然沒什麼技巧,但是方便

//SafeDelete

#ifndef SafeDelete

#define SafeDelete(p) { if(p) { delete (p); (p)=NULL; } }

#endif

//SafeDeleteArray

#ifndef SafeDeleteArray

#define SafeDeleteArray(p) { if(p) { delete[] (p); (p)=NULL; } }

#endif

//SafeDeleteArray2D

#ifndef SafeDeleteArray2D

#define SafeDeleteArray2D(p,max_order) { if(p) { for( int i = 0; i < max_order; ++i ) { SafeDeleteArray(p[i]); } SafeDeleteArray(p); } }

#endif

//SafeRelease

#ifndef SafeRelease

#define SafeRelease(p) { if(p) { (p)->Release(); (p)=NULL; } }

#endif

#if defined(DEBUG) | defined(_DEBUG)//debug version

//SafeError (HRESULT hr;) with a error messagebox

#ifndef SafeError

#define SafeError(x) { hr = x; if( FAILED(hr) ) { DXTrace( __FILE__, (DWORD)__LINE__, hr, #x, true ); } }

#endif

//SafeReturn (HRESLT hr;) with a error messagebox

#ifndef SafeReturn

#define SafeReturn(x) { hr = x; if( FAILED(hr) ) { return DXTrace( __FILE__, (DWORD)__LINE__, hr, #x, true ); } }

#endif

#else//release version

//SafeError

#ifndef SafeError

#define SafeError(x) { hr = x; }

#endif

//SafeReturn (HRESULT hr;)

#ifndef SafeReturn

#define SafeReturn(x) { hr = x; if( FAILED(hr) ) { return hr; } }

#endif

#endif//end define

宏技巧還有很多,上面介紹的只是我隨性想到的。與其把宏編程當作編程技巧不如當作寫作技巧。宏是一種填字遊戲,需要發揮你的才智去擴展它。不要因為inline函數而放棄了宏,它沒你想像的那麼糟糕。宏是效率利器,位運算的法寶。 不要拒絕它,也不要害怕老程序員的代碼裡大堆大堆的宏定義,試著去讀它,你能從中領悟前人的智慧。希望我的這篇小文章能讓你喜歡上宏。


分享到:


相關文章: