__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__),但无法推导出函数名本身。
立即学习“C++免费学习笔记(深入)”;
- 试图通过宏拼接生成函数名(如
#define MY_FUNC __func__)是无效的——宏在定义时不捕获上下文 - 运行时反射(如获取 mangled 名)需借助平台 ABI(如
abi::__cxa_demangle),复杂且非标准,不推荐仅为了函数名而使用
实际使用建议
- 日常开发和日志中,优先使用 __func__ —— 标准、简洁、语义明确
- 调试时若需完整签名,可临时用 __PRETTY_FUNCTION__,但避免写入稳定日志格式
- 跨平台项目中不要依赖 __FUNCTION__,除非已做编译器检查并提供 fallback
- 注意:__func__ 在内联函数中展开为被调用处的函数名(即实际内联位置的函数),不是调用者的函数名










