慢吞云雾缓吐愁 发表于 2022-6-20 08:32:17

聊聊 C# 方法重载的底层玩法

最近在看 C++ 的方法重载,我就在想 C# 中的重载底层是怎么玩的,很多朋友应该知道 C 是不支持重载的,比如下面的代码就会报错。
#include <stdio.h>

int say() {
        return 1;
}
int say(int i) {
        return i;
}

int main()
{
        say(10);
        return 0;
}https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/4dbcd8b1c6c544fcade861204b678774~tplv-k3u1fbpfcp-zoom-1.image
从错误信息看,它说 say 方法已经存在了,尴尬。。。
一:为什么 C 不支持

要想寻找答案,需要了解一点点底层知识,那就是编译器在编译 C 方法时会将 函数名 作为符号添加到 符号表 中,这个 符号表 就是 call 到 say方法字节码中间的一个载体,画个图大概就是这样。
https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/e96aafb96880428890de94739b4b4b82~tplv-k3u1fbpfcp-zoom-1.image
简而言之,call 先跳转到 符号表, 然后再 jmp 到 say 方法,问题就出现在这里,符号表是一种类字典结构,是不可以出现 符号 相同的情况。对了,在 windbg 中我们可以用 x 命令去搜索这些符号,
为了论证我的说法,可以在汇编层面给大家验证下,修改代码如下:
#include <stdio.h>

int say(int i) {
        return i;
}

int main()
{
        say(10);
        return 0;
}接下来再看下汇编。
--------------- say(10) -----------

00C41771push      0Ah
00C41773call      _say (0C412ADh)

--------------- 符号表 -----------

00C412ADjmp         say (0C417B0h)

--------------- say body -----------

00C417B0push      ebp
00C417B1mov         ebp,esp
00C417B3sub         esp,0C0h
00C417B9push      ebx
00C417BApush      esi
00C417BBpush      edi
00C417BCmov         edi,ebp
00C417BExor         ecx,ecx
00C417C0mov         eax,0CCCCCCCCh
00C417C5rep stos    dword ptr es:
00C417C7mov         ecx,offset _2440747F_ConsoleApplication6@c (0C4C008h)
...知道了原理后,我们再看看 C++ 是如何在 符号表 上实现唯一性突破。
二:C++ 符号表突破

为了方便讲述,我们先上一段 C++ 方法重载的代码。
using namespace std;class Person{public:        void sayhello(int i) {                cout
页: [1]
查看完整版本: 聊聊 C# 方法重载的底层玩法