首先我们先解决一下为什么C++支持函数重载,而C语言不支持?
这里就不得不提起编译链接了;
这是编译链接篇
以这三个简单的文件为例:
预处理阶段: 头文件的展开,条件编译,宏的替换,注释的删除等,最终处理完这些后test.c就会变成test.i,add.c就会变成add.i;
编译阶段: 词义分析,符号汇总(函数名,全局变量),语法分析,语义分析,将代码转换为汇编代码,最终处理完这些后test.i会变成test.s,add.i会变成add.s,注意这里只是对符号进行了汇总还没有获取到符号的地址;
3. 汇编阶段: 形成符号表,将汇编语言转换为二进制的机器语言,然后test.s变成test.o,add.s变成add.o;
4. 链接阶段: 进行符号表的合并和重定位,段表的合并,相当于把多个.c文件链接起来了,最后在windows环境下生成.exe文件,在Linux环境下生成a.out(可以改),这里就能获得最终的函数地址;
这是Linux下gcc (C语言编译器) 编译后的结果:
我们发现C语言在编译期间函数名并未发生改变;
这是Linux下g++ (C++编译器) 编译后的结果:
我么发现C++在编译阶段函数名进行了修饰;
C++的函数名字修饰规则是什么?
【_Z+函数名长度+函数名+数据类型首字母】;
综上所述: C语言没办法支持重载,因为同名函数没办法区分。而C++是通过函数修饰规则来区分,只要参数不同,修饰出来的名字就不一样,就支持了重载。
为什么当函数参数列表项同时,返回值类型不同不构成函数重载?
假设函数名字修饰规则中有返回值的写入,那么在链接阶段编译器是无法区分你要调用的是哪个函数;
在windows环境下,vs也有自己的函数名字修饰规则,逻辑上是和Linux下函数名字修饰规则一样的,但是vs中的函数名字的修饰规则太复杂;