函数重载
函数重载:是函数的一种特殊情况,C++允许在同一作用域中声明几个功能类似的同名函数,这些同名函数的形参列表(参数个数 或 类型 或 类型顺序)不同,常用来处理实现功能类似数据类型不同的问题。
要注意的是:只有函数名相同,形参不同(个数\类型\类型顺序不同)才能构成函数重载
而函数名相同,返回值不同的函数不构成函数重载
返回值类型与函数是否重载无关
参数类型不同
int add(int a, int b) { cout << "int:" << a + b << endl; return a + b; } double add(double a, double b) { cout << "double:" << a + b << endl; return a + b; } int main() { add(1,1); add(1.1,2.2); }
参数个数不同
void fun(int a) { cout << a << endl; } void fcun(int a, int b) { cout << a <<" "<< b << endl; } int main() { fun(1); fun(1,2); }
参数类型顺序不同
这里注意:是参数类型顺序不同,而不是参数名顺序不同
int f(int a,double b)和int f(int b,double a)是不构成重载的 void ff(int a, char b) { cout << a << " " << b << endl; } void ff(char a, int b) { cout << a << " " << b << endl; } int main() { ff(10,'a'); ff('a',10); }
1
以上三个情况就是各种类型的函数重载
其实还有一种情况,就是当重载和缺省在一起时:
void fff() { cout << 1 << endl; } void fff(int a = 0) { cout << a << endl; }
上面2个函数都可以通过编译
当我们使用实参对缺省参数赋值fff(1),可以正常运行
但是无参调用时会出现歧义,会报错
fff(),编译器不知道是要调用无参的那么函数还是调用缺省参数函数,发生冲突,无法运行
函数重载是怎样实现的
C语言不支持函数重载,而C++却能支持,C++是如何支持的呢?
这其实是在编译链接过程中,利用函数名修饰规则实现的
我们先来看一下编译链接的过程,如果我们在test.h中声明了函数,在test.cpp中实现,在_test.cpp文件中调用
实验代码如下:
test.h #include <iostream> using namespace std; int add(int a, int b); double add(double a, double b); 1 2 3 4 5 test.cpp #include "test.h" int add(int a, int b) { return a + b; } double add(double a, double b) { return a + b; }
_test.cpp #include "test.h" int main() { add(1,1); add(1.1, 2.2); return 0; }
编译链接过程如下图:
调用函数都会被转换成call+一个地址,这个地址就是函数的地址
所以,这段代码在编译过程中,需要call2次,本来call需要去找到函数的地址,但是函数的定义在test.cpp文件中,地址也在test.i文件中,当前还未链接,所以还找不到地址
下面接着编译链接,在链接时,会生成一个符号表,这里面有函数名和其地址,这时2个文件是链接在一起的了
,之后就会进行找函数地址操作
但是C语言中,规定的是通过函数名进行寻址,因为这里有2个姓名相同的函数名,所以找不到正确的地址
所以C语言才不支持函数重载
下面,我们也通过linux系统,给;能够更方便得观察到函数名修饰规则
我们先在linux环境下创建一个c语言文件test.c
然后我们通过下面这些操作可以看到这个代码的汇编代码:
从汇编代码中找到调用func函数的部分:
这也证实了C语言是通过函数名进行寻址的
下面我们看一下C++是什么样的
先写一个cpp文件
然后还是观察它的汇编代码
可以看见汇编代码中,2个func的名字变了,这里不是func了
这其实就是函数名修饰规则
第一个调用的函数名是_Z4funci
-Z是编译器规定的长度
4是指函数名func的长度
func就是原函数命
最重要的就是i,它jiusint类型的缩写
同理,第二个函数名最后的id就是int和double类型的缩写
这里也能看出来为什么饭返回值不同不会构成函数重载?
因为返回值不会进入到函数名修饰规则里
参数会进入函数名修饰规则里,参数不同,最后函数名也不同
所以到这里就理解了为什么C++支持函数重载了
最后我们思考一个问题
如果我们把函数名修饰规则修改,允许返回值的类型以某种方式进入规则中,那么返回值不会是否会导致函数重载?
答案是也不可以
因为如果遇到如下的代码,2个函数的函数名相同,没有参数或参数都相同,只有返回值不同
int a() { printf("int\n"); } double a() { printf("double\n"); } int main() { a(); return 0; }
这样到了汇编阶段,调用函数时返回值类型是体现不出来的,所以编译器也不知道到底是调用哪个函数
所以不论怎样,返回值类型不同不会导致函数重载
————————————————