Pau*_*ton 6 c++ debugging macros logging c-preprocessor
最近我一直在阅读Scott Meyers的Effective C++ Second Edition,以改进C++最佳实践.他列出的一个项目鼓励C++程序员避免使用预处理器宏并且"更喜欢编译器".他说,除了#include和#ifdef/#ifndef之外,C++中几乎没有宏的原因.
我同意他的推理,因为你可以完成以下宏
#define min(a,b) ((a) < (b) ? (a) : (b))
Run Code Online (Sandbox Code Playgroud)
具有以下C++语言功能
template<class T>
inline const T & min(const T & a, const T & b) {
return a < b ? a : b;
}
Run Code Online (Sandbox Code Playgroud)
其中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
Run Code Online (Sandbox Code Playgroud)
这个宏提供了令人难以置信的实用程序,我希望将其合并到我的C++程序中.编写有用的日志语句非常简单
CCLOG(@"Error in x due to y");
Run Code Online (Sandbox Code Playgroud)
更好的是,如果COCOS2D_DEBUG设置为0,那么这些陈述永远不会被看到.检查条件语句以查看是否应使用日志语句没有任何开销.这在从开发过渡到生产时非常方便.如何在C++中重新创建相同的效果?
那么这种类型的宏属于C++程序吗?有更好的,更多的C++方式吗?
首先,斯科特的声明是在宏被过度使用的时候做出的,这是出于历史原因.虽然通常是正确的,但有一些情况下宏是有意义的.其中有一些是日志记录,因为只有一个宏可以自动插入__FILE__和__LINE__.此外,只有一个宏可以解决绝对没有(虽然根据我的经验,这不是一个大问题).
您展示的宏在C++中并不常见.日志记录有两种常见的变体:
#define LOG( message ) ... << message ...
Run Code Online (Sandbox Code Playgroud)
它允许表单中的消息" x = " << x,并且可以通过重新定义宏来完全抑制,并且
#define LOG() logFile( __FILE__, __LINE__ )
Run Code Online (Sandbox Code Playgroud)
其中logFile返回的一个包装std::ostream,它定义operator<<,并允许这样的事情:
LOG() << "x = " << x;
Run Code Online (Sandbox Code Playgroud)
通过这种方式,LOG()
将始终评估右侧的所有表达式,但正确完成后,除非日志处于活动状态,否则不会进行格式化.
| 归档时间: |
|
| 查看次数: |
1605 次 |
| 最近记录: |