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函数而放弃了宏,它没你想像的那么糟糕。宏是效率利器,位运算的法宝。 不要拒绝它,也不要害怕老程序员的代码里大堆大堆的宏定义,试着去读它,你能从中领悟前人的智慧。希望我的这篇小文章能让你喜欢上宏。


分享到:


相關文章: