函数重载
什么是函数重载
函数重载是指在同一作用域内,函数名相同而形参列表不同的一组函数。
编译器首先将调用的实参与重载集合中每一个函数的形参作比较,然后根据比较的结果决定调用哪一个函数。
为什么要函数重载
重载函数通常用来命名一组功能相似的函数,增强了程序的可读性,函数重载在一定程度上减轻了程序员起名字,记名字的负担。
比如操作符重载在本质上也是函数重载,其大大丰富了已有操作符的含义,方便记忆和使用。
函数重载中要注意的一些细节
函数重载与作用域
如果我们在内层作用域中声明名字,那么它将隐藏外层作用域中声明的同名实体,在不同的作用域中无法重载函数名。
函数匹配【重载确定】
函数匹配【重载确定】是指一个过程,在这个过程中我们把函数调用与一组重载函数中的某一个关联起来。
编译器首先将调用的实参与重载集合中每一个函数的形参作比较,然后根据比较的结果决定调用哪一个函数。
大多数情况下,重载集合中的函数区别明显,它们要么是函数形参的数量不同,要么是函形参类型毫无关系,这种情况下确定调用哪一个函数是比较容易的。但是当两个重载函数的形参数量相同且形参类型之间可以相互转换时,如何选择函数就值得我们注意了,接下来我们来详细讨论函数匹配的具体过程:
- 确定本次调用对应的重载函数集,集合中的函数称为候选函数。
- 候选函数的两个特点:
- 与被调用的函数同名
- 其声明在调用点可见
- 考察本次调用提供的实参,然后从候选函数中选出能被这组实参调用的函数,这些新选出的函数称为可行函数。
- 可行函数的两个特点:
- 其形参数量与本次调用提供的实参数量相等
- 每个实参的类型与对应的形参的类型相同,或者实参类型可以转换成对应的形参类型。
-
从可行函数中选出与本次调用最佳匹配函数,基本思想是实参类型与形参类型越接近它们匹配的越好。
最佳匹配的实现实现等级排序:- 精确匹配
- 实参类型和形参类型相同 - 实参从数组类型或者函数类型转换为对应的指针类型 - 向实参中添加顶层const或者删除顶层const。
- 通过const转换实现的匹配
- 通过类型提升实现的匹配
- 通过算数类型转换或者指针转换实现的匹配
- 通过类类型转换实现的匹配
当某一个调用具有二义性而无法选择出最佳匹配函数时,编译器会因为这个滴啊用具有二义性而拒绝其请求:因为从整体上无法判断孰优孰劣。
重载和const形参
一个拥有顶层const的形参和一个没有顶层const的形参无法区分,比如:
int text(int a);
int text(const int a);//这属于重复定义
如果函数的形参是某种类型的引用或指针,则通过区分其指向的是常量对象还是非常量对象可以实现函数重载,如果具有底层const属性则可以区分,比如:
int text(int &a);
int text(const int &a);
int texta(int *a);
int texta(const int *a);//这里的const是底层const
如果两个函数唯一的区别是它的指针形参指向常量或者非常量或者它的引用与常量或者非常量绑定,那么编译器通过实参是否是常量决定选用那个函数:如果实参是指向常量的指针或者与常量绑定的引用,那么将调用形参是const*或者const&的函数,反之调用形参是普通指针或者引用的函数。
const_cast和函数重载
当我们想要处理常量对象或者非常量对象的时候我们一般会将函数的形参声明为常量,这样处理可以使得实参不论是常量还是非常量时都可以调用该函数,如下面这个例子所示:
const string &text(const string &s1, const string &s2) {
return (s1.size() > s2.size()) ? s1 : s2;
}
但是这样处理有一个显而易见的问题是:无论实参是常量还是非常量其返回类型都是const string &,如果我们希望当实参是非常量的时候其返回类型是string&而不是const string&呢?由之前的博文我们知道,const_cast在函数重载这样的情形中最为有用,我们可以这样处理:
string &text(string &s1, string &s2) {
auto &r = text(const_cast<const string &>(s1), const_cast<const string &>(s2));
return const_cast<string &>(r);
}
这样以来我们就可以实现当实参是const时返回类型也是const,当实参是非常量时其返回类型也是非常量类型了。
来源:CSDN
作者:Feriii
链接:https://blog.csdn.net/qq_43923676/article/details/104148965