1.函数重载的概念
C++允许在同一作用域中声明几个功能类似的同名函数,这些同名函数的形参(参数个数/类型/类型顺序)不同,常用来处理实现功能类似数据类型不同的问题。
1.2.属于函数重载的三种形式
1.参数类型不同构成函数重载
Add(int a, int b);
Add(double a, double b);
2.参数个数不同构成函数重载
Add(int a, int b);
Add(int a);
3.参数类型顺序不同构成函数重载
Add(int a, double b);
Add(double b, int a);
4.函数仅有返回值不同不能构成重载,因为调用函数的地方只用了参数,无法区分用的是哪个函数。
int Add(int a, int b)
{
//...
}
void Add(int a, int b)
{
//...
}
2.C++支持函数重载的原理
2.1.编译知识补充
在C/C++中,程序要运行,需要经历以下几个阶段:
预处理(.i)->编译(.s)->汇编(.o)->链接
补充:
- 预处理:预处理指令
- 编译:语法分析、词法分析、语义分析、符号汇总
- 汇编:形成符号表
- 链接:合并段表,符号表的合并与重定位
当项目存在多个源文件时,若一个源文件调用了另一个源文件中的函数(a.cpp调用了b.cpp中定义的的ADD函数时),在文件编译以后、链接之前,汇编文件a.o中并没有保存ADD函数的地址,当链接器发现a.o调用ADD但是却没有ADD的地址时,就会从b.o的符号表中寻找ADD函数的地址并链接给a.o。
2.2.函数重载的原理
那么在链接时,面对重载函数,链接器是如何识别同名函数的呢?
C语言:编译器不会对函数名进行修饰,原来叫什么编译后还是叫什么。
C++:编译器会对函数名进行修饰,不同的平台修饰规则不同。
在Linux下举例:
Add(int a, int b);
Add(double a, double b);
//C++在Linux下会将Add修饰为_Z3Addii(0x313131310)和_Z3Adddd(0x313131320)
//其中3表示函数名的长度,后面的ii、dd分别表示参数的类型int、int和double、double
//而不是直接用Add(0x313131310)识别,所以能够区分同名的的函数
总结:C++在编译器下会对函数名进行修饰,在编译完成后,函数名会通过不同的参数而发生变化,所以能够识别同名函数,实现函数重载。而C语言不会对函数名修饰,不能识别同名函数,所以不支持函数重载。