近日无聊,奉献一些宏编程技巧给大家。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函数而放弃了宏,它没你想像的那么糟糕。宏是效率利器,位运算的法宝。 不要拒绝它,也不要害怕老程序员的代码里大堆大堆的宏定义,试着去读它,你能从中领悟前人的智慧。希望我的这篇小文章能让你喜欢上宏。
閱讀更多 一個程序員的奮鬥史 的文章