C++如何获取当前函数的名称?(预定义宏用法)

__func__ 是 C++11 引入的预定义标识符,用于获取当前函数未限定名,类型为 const char[],非宏、安全可靠,支持普通函数、成员函数及 C++23 起的 lambda。

在 C++ 中,可以使用预定义宏 __func__ 获取当前函数的名称,这是 C++11 标准引入的、最直接且可移植的方式。

使用 __func__ 获取函数名

__func__ 是一个隐式声明的静态局部常量字符串(类型为 const char[]),在每个函数作用域内自动存在,值为该函数的未限定名(即不带类名、命名空间或返回类型的纯函数名)。

  • 它不是宏,而是一个语言特性,因此不受宏展开顺序影响,更安全可靠
  • 适用于所有普通函数、成员函数、lambda(C++23 起支持 lambda 内的 __func__
  • 示例:void foo() { std::cout

兼容旧代码:__FUNCTION____PRETTY_FUNCTION__

这两个是常见编译器(GCC、Clang)扩展,非标准但广泛支持:

  • __FUNCTION__ 行为与 __func__ 基本一致,可看作其别名,但属于编译器扩展
  • __PRETTY_FUNCTION__ 提供更详细的签名信息(含返回类型、参数、类作用域等),适合调试输出
    例如在 class A { void bar(int x) {} } 中,__PRETTY_FUNCTION__ 可能输出 "void A::bar(int)"
  • 注意:__PRETTY_FUNCTION__ 在不同编译器中格式略有差异,不可用于解析逻辑

不能用 __FILE____LINE__ 替代函数名

__FILE____LINE__ 分别返回源文件路径和行号,它们与函数名无关。虽然组合使用可辅助定位(如日志中打印 __FILE__ ":" STRINGIFY(__LINE__) " in " __func__),但无法推导出函数名本身。

  • 试图通过宏拼接生成函数名(如 #define MY_FUNC __func__)是无效的——宏在定义时不捕获上下文
  • 运行时反射(如获取 mangled 名)需借助平台 ABI(如 abi::__cxa_demangle),复杂且非标准,不推荐仅为了函数名而使用

实际使用建议

  • 日常开发和日志中,优先使用 __func__ —— 标准、简洁、语义明确
  • 调试时若需完整签名,可临时用 __PRETTY_FUNCTION__,但避免写入稳定日志格式
  • 跨平台项目中不要依赖 __FUNCTION__,除非已做编译器检查并提供 fallback
  • 注意:__func__ 在内联函数中展开为被调用处的函数名(即实际内联位置的函数),不是调用者的函数名