通过C++的函数重载的学习,我相信大家很疑惑C++支持函数重载,C语言为啥不行?现在就给你揭开疑惑的面纱。
目录
一、小知识:
在C/C++中,一个程序要运行起来,需要经历以下几个阶段:预处理、编译、汇编、链接。
通过上述简单了解,我们知道一个项目由多个头文件和源文件组成。
二、小问题:
那在a.cpp中调用了b.cpp中定义的Add函数时,编译后,链接前,a.o的目标文件中没有Add的函数地址,因为Add是在b.cpp中定义的,所以Add的地址在b.o中。
这怎么办呢?
所以链接阶段就是专门处理这种问题,链接器看到a.o调用Add,但是没有Add的地址,就会到b.o的符号表中找Add的地址,然后链接到一起。
那么链接时,面对Add函数,链接接器会使用哪个名字去找呢?这里每个编译器都有自己的函数名修饰规则。由于Windows下vs的修饰规则过于复杂,而Linux下g++的修饰规则简单易懂,下面我们使用了g++演示了这个修饰后的名字。
以这段代码为例
int Add(int a, int b)
{
return a + b;
}
void func(int a, double b, int* p)
{}
int main()
{
Add(1, 2);
func(1, 2, 0);
return 0;
}
a.采用C语言编译器编译后结果

结论:在linux下,采用gcc编译完成后,函数名字的修饰没有发生改变。
b.采用C++编译器编译后结果

结论:在linux下,采用g++编译完成后,函数名字的修饰发生改变,编译器将函数参数类型信息添加到修改后的名字中。
三、得出结论:
通过上面我们可以看出gcc的函数修饰后名字不变。而g++的函数修饰后变成<_Z+函数长度+函数名+类型首字母>。
通过这里就理解了C语言没办法支持重载,因为同名函数没办法区分。而C++是通过函数修饰规则来区分,只要参数不同,修饰出来的名字就不一样,就支持了重载。
由此得出:
C++支持函数重载的原理--名字修饰。
四、小拓展:
在C++上的这段代码
int fun(int a, int b);
int fun2(int a, char b);
char fun3(char a, char b);
int main()
{
fun(1, 2);
fun2(1, 'c');
fun3('1', '2');
//system("pause");
return 0;
}

我们仔细研究发现一个函数在C++中的符号是以?函数名@@YA开头,之后是H或者D,最后是以@Z结尾,共三部分。且大胆推测,在第二部分中H表示int ,D表示char,且第一个表示返回值,之后的表示函数的参数。
如int fun(char a, char b, int c);就是 ?fun@@YAHDDH@Z
又对比Linux会发现,windows下vs编译器对函数名字修饰规则相对复杂,但道理都是类似的。
C/C++函数调用约定和名字修饰规则--有兴趣好奇的同学可以看看这个博客:

905

被折叠的 条评论
为什么被折叠?



