深度理解函数重载:为什么c语言不支持函数重载?

一、什么是函数重载?

在自然语言中,一个词可以有多重含义,人们可以通过上下文来判断该词真实的含义,我们就说该词被重载了。因此,我们可以推出,函数重载是指 同一作用域中 声明几个功能类似 的同名函数 ,这 些同名函数的 形参列表 ( 参数个数 或 类型 或 类型顺序 ) 不同 ,常用来处理实现功能类似数据类型
不同的问题。
我们判断两个函数是否重载的关键在于,第一,判断函数名是否相同。第二,是否有参数类型、参数个数或参数类型顺序不同。而不是关注两个函数的返回类型是否相同,这是无关的。
下面是几个函数重载的例子:
特别注意这第三种情况:是函数 类型顺序不同,而不是 参数顺序不同。若我将第二个函数的参数改为(int b, char a),则只是实现了参数的顺序不同,则这两个函数不构成重载!!

二、为什么c不支持函数重载?

1.编译与链接

首先我们要找到,一个c/c++程序要运行起来,需要经过预处理、编译、汇编、链接四个阶段。下面我们先来回顾一下各个阶段编译器都做了什么事情。预处理:进行头文件的替换、宏的替换。编译:进行语法分析、词法分析、语义分析、符号汇总。汇编:生成二进制指令,生成符号表。链接:合并段表,进行符号表的合并和重定位。

我们假设两个文件分别是A.cpp和B.cpp,在B.cpp中,我进行了对函数ADD的定义。而在A.cpp中我调用了此ADD函数。由于每个文件的编译都是单独进行的,因此在链接前,编译器无法在A.cpp中找到ADD的地址,(因为ADD的定义在文件B.cpp中),所以在A.cpp中进行了对函数ADD的声明,相当于给了编译器一个承诺。而在链接过程中,将符号表合并后,链接器可通过符号表找到ADD的地址,相当于兑现了承诺。

2.函数名修饰规则

那么链接时,面对Add函数,链接接器会使用哪个名字去找呢?这里每个编译器都有自己的函数名修饰规则,由于Windows环境下的修饰规则较为复杂,所以这里用Linux环境进行演示。

采用c语言的编译器编译后结果:

我们可以看到,编译完成后,函数名字并没有被修改,而是直接使用了函数名。

采用c++的编译器编译后结果:

采用g++编译完成后,函数名字的修饰发生改变,编译器将函数参数类型信息添加到修改后的名字中。变成了[Z+函数长度+函数名+类型首字母],这样就使链接器能精准地找到需要的函数,而不是错误地找成了同名的函数。

这样我们就知道了c语言不支持函数重载的原因:因为c语言的编译器不会对函数名字进行修饰和改变,而是直接使用其函数名,这使得同名函数无法区分。而c++通过函数修饰来区分,只要函数参数不同,修饰出来的名字也就不同,从而便支持了重载。

同时,我们也能找到为什么函数返回值不同不能构成重载。若函数名和函数参数都相同,返回值不同,编译时修饰出来的名字是一样的,也就无法区分。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值