函数重载
顾名思义,可以命名相同的函数,当然,不是在不同的命名空间里。
定义
函数的一种特殊情况,C++允许在同一作用域中声明几个功能类似的同名函数,这
些同名函数的形参列表(参数个数 或 类型 或 类型顺序)不同,常用来处理实现功能类似数据类型不同的问题。
参数类型不同
#include <iostream> using namespace std; int add(int x, int y) { return x + y; } double add(double x, double y) { return x + y; } int main() { int a; int b; double c; double d; cin >> a >> b; cin >> c >> d; int sum; sum = add(a, b);//传的两个值都是整形 cout << sum << endl; sum = add(c, d);//传的两个值都是双精度浮点型 cout << sum << endl; return 0; }
这里就自动识别参数中不同数据类型的传值应该去哪个函数。
参数的个数不同
#include <iostream> using namespace std; int add(int x) { return x; } int add(int x, int y) { return x + y; } int main() { int a; int c; int d; cin >> a; cin >> c >> d; int sum; sum = add(a); cout << sum << endl; sum = add(c, d); cout << sum << endl; return 0; }
这里是自动识别参数的个数。
不同数据类型的参数顺序不同
#include <iostream> using namespace std; int add(int x , char y) { return x + y; } int add(char x, int y) { return x + y; } int main() { int a; char b; char c; int d; cin >> a >> b; cin >> c >> d; int sum; sum = add(a, b); cout << sum << endl; sum = add(c, d); cout << sum << endl; return 0; }
这里必须是参数不同的数据类型,不然编译器无法判断传入哪个函数
例:
这里就产生了歧义,也叫做二义性。
C++支持函数重载的原理–名字修饰
在C/C++中,一个程序要运行起来,需要经历以下几个阶段:预处理、编译、汇编、链接。
因为一个项目中,有很多个头文件和源文件组成,函数是很重要的部分,两个不同文件中,一个调用函数一个是函数的定义,这个时候就要找函数的地址把他们链接起来,那么找地址的部分在函数重载是怎么实现的?
我们知道,函数名就是函数地址,那么编译器就会用修饰规则去根据函数重载的函数名和参数进行修饰,变成两个相对接近的名字。
C和C++的符号表区别是这样的:
地址和函数名是编的,但是原理是这样的,C语言中在链接的过程中只有函数名被修饰,C++中函数名和参数一起被修饰。
让我们看一下Linux环境下的g++中C和C++链接时候的情况:
采用C语言编译器编译后结果:
结论:在linux下,采用gcc编译完成后,函数名字的修饰没有发生改变。
采用C++编译器编译后结果:
结论:在linux下,采用g++编译完成后,函数名字的修饰发生改变,编译器将函数参
数类型信息添加到修改后的名字中。
我们可以看出gcc的函数修饰后名字不变。而g++的函数修饰后变成【_Z+函数长度
+函数名+类型首字母】。
再来看看Windows下名字修饰规则
对比Linux会发现,windows下vs编译器对函数名字修饰规则相对复杂难懂,但道理都
是类似的,我们就不做细致的研究了。
通过这里就理解了C语言没办法支持重载,因为同名函数没办法区分。而C++是通过函数修饰规则来区分,只要参数不同,修饰出来的名字就不一样,就支持了重载。
如果两个函数函数名和参数是一样的,返回值不同是不构成重载的,因为调用时编译器没办法区分,调用主要是看参数,和返回值无关。