最近我一直在阅读 Scott Meyers 的 Effective C++ Second Edition,以改进 C++ 最佳实践。他列出的项目之一鼓励 C++ 程序员避免使用预处理器宏并“更喜欢编译器”。他甚至说除了#include 和#ifdef/#ifndef 之外,几乎没有理由在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;
}
其中 inline 为编译器提供了删除函数调用并插入内联代码和模板的选项,这些代码和模板可以处理具有重载或内置 > 运算符的多种数据类型。
编辑——如果 a 和 b 的数据类型不同,此模板声明将不完全匹配所述宏。有关示例,请参见 Pete 的评论。
但是,我很想知道在 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++ 的方式来做到这一点?