最近,我一直在閱讀Scott Meyers的Effective C++第二版,以改進C++最佳實踐。他列出的項目之一鼓勵C++程序員避免預處理器宏和'喜歡編譯器'。他甚至說除了#include和#ifdef /#ifndef之外,在C++中幾乎沒有宏的原因。調試日誌語句的預處理器宏是否在C++中佔有一席之地?
我同意他的推理,你可以完成下面的宏
#define min(a,b) ((a) < (b) ? (a) : (b))
與下面的C++語言功能
template<class T>
inline const T & min(const T & a, const T & b) {
return a < b ? a : b;
}
,其中內聯給出了編譯器刪除函數調用的選項,插入內聯代碼和可以處理多個數據類型的模板,這些數據類型具有超載或內置>運算符。
編輯 -如果a和b的數據類型不同,此模板聲明將不會完全匹配所述的宏。請參閱皮特的評論爲例。
不過,我很想知道,如果使用宏是爲了調試日誌記錄在C++中的有效使用。如果我在下面介紹的方法不是很好的做法,有人會建議一種替代方法嗎?
我在Objective-C中被編碼的最後一年,我最喜歡的2D引擎(cocos2d的)中的一個使用的宏創建日誌記錄語句。這個宏如下:
/*
* if COCOS2D_DEBUG is not defined, or if it is 0 then
* all CCLOGXXX macros will be disabled
*
* if COCOS2D_DEBUG==1 then:
* CCLOG() will be enabled
* CCLOGERROR() will be enabled
* CCLOGINFO() will be disabled
*
* if COCOS2D_DEBUG==2 or higher then:
* CCLOG() will be enabled
* CCLOGERROR() will be enabled
* CCLOGINFO() will be enabled
*/
#define __CCLOGWITHFUNCTION(s, ...) \
NSLog(@"%s : %@",__FUNCTION__,[NSString stringWithFormat:(s), ##__VA_ARGS__])
#define __CCLOG(s, ...) \
NSLog(@"%@",[NSString stringWithFormat:(s), ##__VA_ARGS__])
#if !defined(COCOS2D_DEBUG) || COCOS2D_DEBUG == 0
#define CCLOG(...) do {} while (0)
#define CCLOGWARN(...) do {} while (0)
#define CCLOGINFO(...) do {} while (0)
#elif COCOS2D_DEBUG == 1
#define CCLOG(...) __CCLOG(__VA_ARGS__)
#define CCLOGWARN(...) __CCLOGWITHFUNCTION(__VA_ARGS__)
#define CCLOGINFO(...) do {} while (0)
#elif COCOS2D_DEBUG > 1
#define CCLOG(...) __CCLOG(__VA_ARGS__)
#define CCLOGWARN(...) __CCLOGWITHFUNCTION(__VA_ARGS__)
#define CCLOGINFO(...) __CCLOG(__VA_ARGS__)
#endif // COCOS2D_DEBUG
這個宏提供了令人難以置信的效用,我將要合併到我的C++程序中。編寫有用的日誌語句很簡單,只要
CCLOG(@"Error in x due to y");
什麼是更好的是,如果COCOS2D_DEBUG設置爲0,那麼這些語句永遠看不到光明的一天。檢查條件語句以查看是否應使用日誌語句沒有開銷。從開發過渡到生產時這很方便。如何在C++中重新創建相同的效果?
那麼,這類型的宏在C++程序屬於?有沒有更好的,更多的C++方式來做到這一點?
我相信你的「CCLOG()」是一個很好的例子,宏是有用和適當的。恕我直言... – paulsm4
嗯,'min'模板函數不會執行與宏相同的操作。試用'min(1,2L)'。 –
@PeteBecker我不是模板的大師,但是可以這樣做,因爲1是一個int和2L是長?我提供的模板聲明只會爲兩個相同類型的對象生成函數。 –