如何在C++中实现类装饰器式的函数调用调试自动打印?
C++实现函数调用自动打印的装饰器式方案
因为C++没有原生的装饰器语法,我们可以通过宏模拟或模板包装两种方式实现你想要的自动打印函数调用的效果,以下是具体实现:
方法一:宏模拟装饰器(最贴近需求)
这种方法直接通过宏改写函数定义,自动在函数开头插入打印语句,完全不需要手动调用打印宏。
实现代码
#include <iostream> // 基础打印逻辑:自动获取当前函数名 #define PRINT_CALL() std::cout << "(CALL) " << __func__ << std::endl; // 装饰无参数函数的宏 #define CALL_DECORATOR_VOID(ret_type, func_name) \ ret_type func_name() { \ PRINT_CALL(); // 装饰带参数函数的宏(支持任意参数列表) #define CALL_DECORATOR(ret_type, func_name, ...) \ ret_type func_name(__VA_ARGS__) { \ PRINT_CALL();
使用示例
// 装饰无参数函数 CALL_DECORATOR_VOID(void, foo) // 原函数逻辑 std::cout << "Executing foo..." << std::endl; } // 装饰带参数函数 CALL_DECORATOR(int, add, int a, int b) // 原函数逻辑 return a + b; } int main() { foo(); // 输出:(CALL) foo → Executing foo... add(2, 3); // 输出:(CALL) add }
方法二:模板包装器(更优雅的类型安全方案)
利用C++11的lambda和模板,将原函数包装成自动打印的新函数,适合需要保留原函数的场景。
实现代码
#include <iostream> #include <functional> // 无参数函数的包装 template<typename Ret> auto decorate_call(Ret(*func)(), const char* func_name) { return [func, func_name]() { std::cout << "(CALL) " << func_name << std::endl; return func(); }; } // 带任意参数的函数包装(变参模板) template<typename Ret, typename... Args> auto decorate_call(Ret(*func)(Args...), const char* func_name) { return [func, func_name](Args... args) { std::cout << "(CALL) " << func_name << std::endl; return func(std::forward<Args>(args)...); }; } // 辅助宏:快速替换原函数(作用域内有效) #define DECORATE(func) \ auto func##_original = func; \ auto func = decorate_call(func##_original, #func);
使用示例
void foo() { std::cout << "Executing foo..." << std::endl; } int add(int a, int b) { return a + b; } int main() { // 自动装饰foo函数 DECORATE(foo); foo(); // 输出:(CALL) foo → Executing foo... // 手动装饰add函数 auto decorated_add = decorate_call(add, "add(int, int)"); std::cout << decorated_add(2, 3) << std::endl; // 输出:(CALL) add(int, int) → 5 }
注意事项
- 宏模拟方案侵入性强,调试完成后可以批量删除宏定义和装饰语法,不影响原函数逻辑。
- 模板包装方案类型安全,不会污染函数定义,但需要额外的变量或宏辅助替换原函数调用。
内容的提问来源于stack exchange,提问作者Gamoron
相关产品推荐
相关产品推荐

