
C++ 函数重载的实现,依赖于编译器在编译期对函数名进行“修饰”(name mangling),把函数名、参数类型、所在作用域等信息编码进一个唯一符号名中,从而让链接器能区分同名但不同参数的函数。
函数重载的本质不是运行时选择,而是编译期绑定
重载函数在源码中名字相同,但编译器会根据参数类型(包括 const/volatile 限定、引用/指针、是否为模板实例等)和返回类型(仅限 C++20 起对概念约束有影响,常规重载不看返回类型)生成不同的内部符号名。调用时,编译器根据实参类型匹配最佳重载版本,然后调用对应修饰后的函数符号。
- 重载解析发生在编译阶段,不涉及虚函数表或运行时多态
- 返回类型不参与重载决议(除非是 C++20 的 constrained template,但那是另一套机制)
- const 成员函数与非 const 成员函数可构成重载(隐含 this 指针类型不同)
name mangling 是什么:把语义信息编码成链接符号
目标文件中的函数符号不能只叫 foo,否则多个 void foo(int) 和 void foo(double) 会冲突。编译器将函数签名“翻译”成一串唯一、无歧义的底层符号名(如 _Z3fooi 或 ?foo@@YAXH@Z),供链接器识别。
- GCC/Clang 使用基于 Itanium ABI 的 mangling 规则(例如 _Z3fooi 表示 3 字符名 foo + 参数 int)
- MSVC 使用自己的方案(如 ?foo@@YAXH@Z,其中 H 表示 int)
- mangling 结果包含:函数名、命名空间/类作用域、参数类型(完整类型,含 const、&、&&、模板实参等)、是否为 static / extern "C" 等
extern "C" 为什么禁用重载
extern "C" 告诉编译器:不要做 name mangling,用 C 风格的简单符号名(如直接叫 foo)。而 C 不支持重载,链接器看到多个同名符号就会报错(multiple definition)。
立即学习“C++免费学习笔记(深入)”;
- 所有 extern "C" 函数必须有唯一名称,即使参数不同也不行
- 头文件中若用 extern "C" 包裹声明,就不能在其中定义重载函数
- 混合使用时:重载函数不能被 extern "C" 声明;反之,extern "C" 函数也不能被重载
如何查看 mangled 名字
调试或排查链接错误时,常需反解符号:
- GCC/Clang:c++filt _Z3fooi → 输出 foo(int)
- MSVC:dumpbin /symbols 查看 obj 中的符号,再用 undname 工具反解
- Linux 下 nm -C a.o 可直接显示 demangled 名(-C 启用自动反解)
- 注意:debug 信息(DWARF/CodeView)里保留原始函数签名,但链接阶段只认 mangled 符号










