什么是函数重载
如果同一个作用域内的几个函数名字相同但形参列表不同,我们称之为重载(overload)函数,C语言不支持重载,原因是这类函数编译后的名称是一样的,而在C++中编译后的名称会因为形参的不同而不同。
判断形参类型是否不同
有时候两个形参列表看起来不一样,实际上是一样的,如下代码中三个函数都是一样的:
typedef std::string MYSTRING;
int func(const std::string&); //省略了形参名
int func(const std::string& value);
int func(const MYSTRING&); //类型相同
重载和const形参
一个拥有顶层const的形参和另一个没有顶层const的形参无法区分开来,下面两个函数是一样的。
int func(const std::string);
int func(std::string);
相反一个底层const形参和另一个没有底层const的形参能区分开来,下面两个函数不一样。
int func(const std::string*);
int func(std::string*);
由于非常量对象可以转换为常量,所以上面的两个函数都能作用于非常量对象,不过一般情况下,当我们传递一个非常量对象或指向非常量对象的指针时,编译器会优先选择非常量版本的函数。
函数匹配
调用重载函数时,有三种可能的结果:
- 编译器找到一个与实参最佳匹配的函数,并生成调用该函数的代码。
- 找不到任何一个函数与调用的实参匹配,此时编译出错。
- 有多于一个函数可以匹配,但是每一个都不是明显的最优选择,此时也会出错,称为二义性调用。
函数匹配的过程如下:
- 选定本次调用的候选函数,候选函数具备两个特征,一时与被调用函数同名,二是声明在调用点可见。
- 从候选函数中选出可行函数,可行函数也有两个特征,一是其形参数量与本次调用的实参数量相等,二是每个实参的类型与对应的形参类型相同或者能转换成形参的类型。
- 寻找最佳匹配,逐一检查实参,寻找形参类型与实参类型最匹配的那个可行函数,比如精确匹配的比需要类型转换的好。如果检查了所有实参后没有任何一个函数能脱颖而出,则编译器报告二义性调用错误。
重载与作用域
如果我们在内层作用域声明名字,它将隐藏外层作用域中声明的同名实体,所以在不同的作用域中无法重载函数名。
void func(std::string value)
{
std::cout << value << std::endl;
}
int main()
{
void func(int value);//新作用域,隐藏了之前的func
system("pause");
return 0;
}