近日無聊,奉獻一些宏編程技巧給大家。C++書裡絕對會千方百計地叫你別用宏而用inline函數取代它,這是給那些品德高尚的程序員的建議,沒人品的程序員都喜歡用宏,比如我:P 。哈哈,說笑的說笑的,宏確實是很好用的東西,只是對於那些未經過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函數而放棄了宏,它沒你想像的那麼糟糕。宏是效率利器,位運算的法寶。 不要拒絕它,也不要害怕老程序員的代碼裡大堆大堆的宏定義,試著去讀它,你能從中領悟前人的智慧。希望我的這篇小文章能讓你喜歡上宏。
閱讀更多 一個程序員的奮鬥史 的文章