4. 几种不同类型的函数重载
总结三种支持函数重载的情况:
- 参数类型不同
int Add(int left, int right) { return left + right; } double Add(double left, double right) { return left + right; }
- 参数个数不同
void f() { cout << "f()" << endl; } void f(int a) { cout << "f(int a)" << endl; }
- 参数类型顺序不同
void f(int a, char b) { cout << "杭州电子科技大学" << endl; } void f(char b, int a) { cout << "圣光机联合学院" << endl; }
(注意:下面这种不属于函数重载):
short Add(short x,short y) { return x+y; } int Add(short x,short y) { return x+y; }
因为它们参数类型,数量,顺序都一样
只是返回值不同,不构成函数重载!
5. C++如何支持函数重载?
在C/C++中,一个程序要运行起来
需要经历以下几个阶段:
- 预处理
- 编译
- 汇编
- 链接
因为c++区别于c在这几个过程中
的差别,所以使C++能够支持函数重载
5.1 C程序为什么不支持函数重载?
定义两个源文件和一个头文件来解释:
- func.h
- func.c
- main.c
在.h文件声明两个函数
int func(int x,int y); int func(int x,double y);
这三个文件会经历以下过程:
- 预处理阶段
主要内容:头文件展开,宏替换
条件编译,去掉注释
这个过程结束后,func.h被展开了
main.c和func.c源文件变成了:
func.i和main.i文件
- 编译阶段
主要内容:语法检查和生成汇编代码
这个过程结束后,func.i和main.i
文件变成了func.s和main.s文件
(此文件中为汇编代码)
- 汇编阶段
主要内容:将汇编代码转换成二进制码
以便机器能够读懂
这个过程结束后,func.s和main.s
文件变成了func.o和main.o文件
注:前面的过程只用了解,真正的主角在下面!
- 链接过程
func.o和main.o文件
以及链接过程是这部分的重中之重
5.2 C程序的链接过程
func.c到func.o和main.c到main.o
都是单线程的
链接过程:
.o的目标文件会合并到一起
其次还需找一些只给了声明的函数
的函数地址
而每一个.o文件都有一个符号表
符号表中存放函数的地址
当main文件要调用这个函数时
会去符号表中找函数的地址
而符号表中两个func函数的地址
编译器不知道应该调用哪个
所以c程序不支持函数重载!
5.3 C++函数名修饰规则
相比起C程序而言,C++新增了一个
函数名修饰规则来支持函数重载
这个规则就是将函数的参数带入符号表
所以参数的类型,数量,顺序不同
代表的是不同的函数,找地址时就不会出错!
我们在C++的汇编代码中找到了
这两个函数对应的部分:
综上所述:
函数参数的类型,数量,顺序不同
那么对应在符号表中的名字就不一样
main文件再去找函数地址时就不会冲突
对比c程序:
c程序符号表中只有一个函数名
函数参数没有参与进来
所以C程序不支持相同函数名的函数
6. 总结以及拓展
前面很多过程只是为了
后面的链接.o文件打基础
所以前面的听不懂也没关系
只需要知道C++有函数名修饰规则
c++的.o文件的符号表的函数名
和函数参数相关
而c程序的符号表和参数无关!
拓展:
C/C++函数调用约定和名字修饰规则
有兴趣好奇的同学可以看看里面
有对vs下函数名修饰规则讲解
🔎 下期预告:引用和内联函数 🔍