__FILE__、__LINE__、__func__的宏替代优化:Logger单例类日志调用简化
更简洁的日志宏方案推荐
嗨,我来给你几个更省心的宏方案,能让你的日志调用变得更简洁,彻底摆脱手动传TRACE参数的麻烦~
方案1:按日志级别封装专属宏(最推荐)
直接把日志级别、追踪参数和调用逻辑全部封装到宏里,调用时只需要传日志内容就行:
// 针对Warning级别定义宏,加上do-while(0)避免语法陷阱 #define LOG_WARNING(msg) do { \ Logger::Warning(__FILE__, __LINE__, __func__, msg); \ } while(0) // 同理可以定义其他级别 #define LOG_ERROR(msg) do { \ Logger::Error(__FILE__, __LINE__, __func__, msg); \ } while(0) #define LOG_INFO(msg) do { \ Logger::Info(__FILE__, __LINE__, __func__, msg); \ } while(0)
优点:
- 调用极致简洁:直接写
LOG_WARNING("something")就行,完全不用管__FILE__这些追踪参数 - 语义清晰:从宏名就能直接看出来日志级别
- 语法安全:
do-while(0)的包裹能避免在if/else等分支里调用宏时出现语法错误(比如宏展开后分号导致的分支匹配问题)
方案2:通用日志宏(支持多级别)
如果不想为每个级别单独写宏,可以用预处理器的连接符##做一个通用宏,适配所有日志级别:
#define LOG(level, msg) do { \ Logger::##level(__FILE__, __LINE__, __func__, msg); \ } while(0)
调用方式:
LOG(Warning, "something"); LOG(Error, "critical issue");
注意事项:
- 要求Logger的各个级别函数名和你传入的
level参数完全一致(比如Logger::Warning对应LOG(Warning, ...)) - 如果函数名是小写(比如
Logger::warning),调用时也要传小写的warning
方案3:支持格式化输出的增强宏
如果你的日志需要类似printf的格式化功能,可以把宏改成支持可变参数:
#define LOG_WARNING(fmt, ...) do { \ Logger::Warning(__FILE__, __LINE__, __func__, fmt, __VA_ARGS__); \ } while(0)
前提是Logger需要有对应的重载函数:
class Logger { public: // 原有的重载 static void Warning(const char* file, int line, const char* func, const char* msg); // 支持格式化的重载 static void Warning(const char* file, int line, const char* func, const char* fmt, ...); };
调用方式:
LOG_WARNING("User %d logged in, ip: %s", userId, ipAddr);
对比原方案的优势
原方案需要写Logger::Warning(TRACE, "something"),而上面的方案只需要写LOG_WARNING("something"),少了重复的Logger::Warning和TRACE,代码更干净,也减少了写错的概率。
内容的提问来源于stack exchange,提问作者Steve H.
相关产品推荐
相关产品推荐

