最近在看 C++ 的方法重载,我就在想 C# 中的重载底层是怎么玩的,很多朋友应该知道 C 是不支持重载的,比如下面的代码就会报错。- #include <stdio.h>
- int say() {
- return 1;
- }
- int say(int i) {
- return i;
- }
- int main()
- {
- say(10);
- return 0;
- }
复制代码
从错误信息看,它说 say 方法已经存在了,尴尬。。。
一:为什么 C 不支持
要想寻找答案,需要了解一点点底层知识,那就是编译器在编译 C 方法时会将 函数名 作为符号添加到 符号表 中,这个 符号表 就是 call 到 say方法字节码 中间的一个载体,画个图大概就是这样。

简而言之,call 先跳转到 符号表, 然后再 jmp 到 say 方法,问题就出现在这里,符号表是一种类字典结构,是不可以出现 符号 相同的情况。对了,在 windbg 中我们可以用 x 命令去搜索这些符号,
为了论证我的说法,可以在汇编层面给大家验证下,修改代码如下:- #include <stdio.h>
- int say(int i) {
- return i;
- }
- int main()
- {
- say(10);
- return 0;
- }
复制代码 接下来再看下汇编。- --------------- say(10) -----------
- 00C41771 push 0Ah
- 00C41773 call _say (0C412ADh)
- --------------- 符号表 -----------
- 00C412AD jmp say (0C417B0h)
- --------------- say body -----------
- 00C417B0 push ebp
- 00C417B1 mov ebp,esp
- 00C417B3 sub esp,0C0h
- 00C417B9 push ebx
- 00C417BA push esi
- 00C417BB push edi
- 00C417BC mov edi,ebp
- 00C417BE xor ecx,ecx
- 00C417C0 mov eax,0CCCCCCCCh
- 00C417C5 rep stos dword ptr es:[edi]
- 00C417C7 mov ecx,offset _2440747F_ConsoleApplication6@c (0C4C008h)
- ...
复制代码 知道了原理后,我们再看看 C++ 是如何在 符号表 上实现唯一性突破。
二:C++ 符号表突破
为了方便讲述,我们先上一段 C++ 方法重载的代码。
[code]using namespace std;class Person{public: void sayhello(int i) { cout |