为啥C++支持函数重载,C语言不行?

通过C++的函数重载的学习,我相信大家很疑惑C++支持函数重载,C语言为啥不行?现在就给你揭开疑惑的面纱。


目录

一、小知识: 

二、小问题:

a.采用C语言编译器编译后结果

b.采用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++函数调用约定和名字修饰规则--有兴趣好奇的同学可以看看这个博客:

C/C++ 函数调用约定-优快云博客

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值