函数重载

如果同一作用域的几个函数名相同但形参列表不同,我们称之为重载函数。这些函数接受的参数类型不同,但是执行的操作非常类似。当调用这些函数时,编译器会根据传递的实参类型推断想要的是哪个函数。函数重载可以在一定程度上减轻程序员起名字,记名字的负担。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.通过类类型转换实现的匹配

posted @ 2017-12-17 18:32  geloutingyu  阅读(236)  评论(0编辑  收藏  举报