函数重载
如果同一作用域的几个函数名相同但形参列表不同,我们称之为重载函数。这些函数接受的参数类型不同,但是执行的操作非常类似。当调用这些函数时,编译器会根据传递的实参类型推断想要的是哪个函数。函数重载可以在一定程度上减轻程序员起名字,记名字的负担。main 函数不能重载。
不允许两个函数除了返回类型外其他所有的要素都相同:
1 int gel(int a, int b){} 2 3 char gel(int a, int b, int c){}//在参数列表不同的情况下允许返回类型不同 4 5 // char gel(int a, int b){}//错误,不允许两个函数除了返回类型外其他要素都相同 6 7 int gel(char a, char b){}
判断两个形参的类型是否相异:
有时候两个形参列表看起来不一样,但实际上是相同的:
1 //下面每对声明的是同一个函数 2 int gel(const int &x); 3 int gel(const int&);//省略了形参名字 4 5 typedef int phone;//phone是int的别名 6 int lou(const phone&); 7 int lou(const int&);
还有前面的博客中说过,在形参中,顶层 const 是可以忽略的。这点在函数重载里面也是一样的:
1 //这四条声明语句是两两等价的 2 int gel(const int a); 3 int gel(int a); 4 5 int lou(int* const a); 6 int lou(int*); 7 8 //下面两条声明语句只有返回值不同,无法通过编译 9 int ting(const int a); 10 double ting(int a);
调用重载函数:
定义了一组重载函数后,我们需要以合理的实参调用它们。函数匹配是指一个过程,在这个过程中我们把函数调用与一组重载函数中的某个关联起来,函数匹配也叫重载确认。编译器首先将调用的实参与重载集合中每个函数的形参进行比较,然后根据比较的结果决定到底调用哪个函数。一般情况下这个过程是比较容易判断的,但有一些情况下比较难看出最终的选择函数。比如:当两个重载函数形参数量相同且可以相互转换时。
调用重载函数时有三种可能的结果:
1.编译器找到一个实参最佳匹配的函数,并生成调用该函数的代码。
2.找不到任何一个函数与调用的实参匹配,此时编译器发出无匹配的错误信息。
3.有多于一个函数可以匹配,但是每种都不是最佳匹配。此时也将发生错误,称为二义性错误。
重载与作用域:
和一般变量作用域规则一样,如果我们在内层作用域中声明名字,它将隐藏外层作用域中声明的同名实体。在不同的作用域中无法重载函数名。事实上,一般来说,将函数声明置于局部作用域内不是一个明智的选择。
函数匹配:
确定候选函数和可行函数:
函数匹配的第一步是选定本次调用对应的重载函数集,集合中的函数称为候选函数。候选函数具备两个特征:一是与被调用函数同名,二是其声明在调用点可见。
第二步考察本次调用提供的实参,然后从候选函数中选出能被这组实参调用的函数,这些新选出的函数称为可行函数。可行函数也有两个特征:一是其形参数量与本次调用提供的实参数量相等,二是每个实参的类型与对应的形参类型相同,或者能转换成形参的类型。
注意:如果函数含有默认实参,则传入的实参数量可能少于它实际使用的实参数量。
寻找最佳匹配:
函数匹配的第三步是从可行函数中选择与本次调用最匹配的函数。在这一过程中,逐一检查函数调用提供的实参,寻找形参类型与实参类型最匹配的那个可行函数:
1.该函数每个实参的匹配都不劣于其他可行函数需要的匹配。
2.至少有一个实参的匹配优于其它任何可行函数提供的匹配。
如果检查了所有实参之后没有任何一个函数脱颖而出,则该调用是错误的。编译器将报告二义性调用的信息。
1 #include <iostream> 2 using namespace std; 3 4 void gel(double x1, double x2){} 5 6 void gel(int x1, int x2){} 7 8 int main(void){ 9 gel(1, 1); 10 gel(0.1, 0.1); 11 // gel(1, 0.1);//错误调用,考虑调用第一个gel函数,1需要转换成double型,考虑调用第二个gel函数则0.1需要转换成int类型 12 return 0; 13 }
实参类型转换:为了确定最佳匹配,编译器将实参类型到形参类型的转换划分成几个等级:
1.精确匹配包括:
a.实参类型和形参类型相同
b.实参从数组类型或者函数类型转换成对应的指针类型
c.向实参添加顶层 const 或者从实参中删除顶层 const
2.通过const转换实现的匹配
3.通过类型提升实现的匹配
4.通过算术类型的转换或指针转换实现的匹配
5.通过类类型转换实现的匹配