共读Primer58.[6.5]参数匹配 Page217
Posted chattyku
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了共读Primer58.[6.5]参数匹配 Page217相关的知识,希望对你有一定的参考价值。
一般来说函数的选择是比较明确的事情,因为有着参数类型和参数数量的标准。
但是如果将类型转换和默认参数都加入到重载函数中,这个过程就变的复杂起来。
来看看一下代码:
void f(); void f(int); void f(int ,int); void f(double, double = 3.14);
在函数的选择过程中分为两步:
1. 找到当前作用域可见的所有名称相同的函数
2. 找到参数数量相等且类型相同或可转换的函数
f(5.6); // 调用 void f(double, double)
那么在一些极端情况下还存在第三部:
3. 寻找最佳匹配
我们知道int和double这两个内置类型是可以进行转化的,所以对上面的函数调用
如果不存在void f(double, double = 3.14), 那么void f(int) 将会被调用
这里void f(double, double=3.14)就是最佳匹配,
那么我们来看看一个更复杂的情况
f(42, 2.56); // 这个调用完全没有精确的匹配函数,编译器应该如何选择?
我们来编码实际操作一下:
#include <iostream> void f(){std::cout << "f()" << std::endl;}; void f(int){std::cout << "f(int)" << std::endl;}; void f(int, int){std::cout << "f(int, int)" << std::endl;}; void f(double, double = 3.14){std::cout << "f(double, double = 3.14)" << std::endl;}; int main() { f(5.6); f(42, 2.56); }
对于上面的代码编译情况如下, 意思是编译器也不知道改掉用哪个,两者处于平等位置,没有最优调用
在此类重载的选择上的原则是
1. 每个参数匹配都不劣于其他的函数匹配。
2. 至少有一个参数的匹配优于其他函数
而本次我们写的调用,
针对第一个参数来说f(int, int) 更匹配,但是第二个参数需要做转换。
针对第二个参数来说f(double,double=3.14)更匹配,但是第一个参数需要转换。
所以对于编译器来说两个可行函数的优劣没有区别,无法进行更优选择,则产生二义性错误。
#include <iostream> void f(){std::cout << "f()" << std::endl;}; void f(int){std::cout << "f(int)" << std::endl;}; void f(int, int){std::cout << "f(int, int)" << std::endl;}; void f(double, double = 3.14){std::cout << "f(double, double = 3.14)" << std::endl;}; int main() { f(5.6); // f(42, 2.56); }
本次代码编译运行结果如下:
实参类型转换
而在参数匹配的过程中类型转换也被划分为几个级别:
1. 精确匹配
以下情形属于精确匹配 :
a. 实参类型和形参类型相同
b. 实参从数组类型或函数类型转换成对应的指着那类型
c. 向实参添加顶层const或者从实参删除顶层const
2. 通过const转换实现的匹配
3. 通过类型提示鞥实现的匹配
4. 通过算术类型转换或指针转换实现的匹配
5. 通过类类型转换实现的匹配
以上的所有情况从上到下的每级的匹配程度低于上一级。
在转换过程中,遵循的原则是从小向打的转换
如short和int的两个匹配类型中如果都需要转换,通常会选择int
void ff(int); void ff(short); ff(‘a‘); // char提升为int
而在算数类型的转换中并没有高低的区别。
void manip(long); void manip(float); manip(3.14); // 调用将产生二义性
const和参数匹配
非const参数可以作为const实参进行传递,但是const实参不能作为非const参数 传递。
所以当一个函数有const和非const两个版本时,那么将根据参数的精确类型来匹配。
否则将可以使用非const实参调用const形参的函数
void lookup(Account &); void lookup(const Account&); const Account a; Account b; lookup(a); // 这个参数只能通过lookup(const Account&)来调用 lookup(b); // 这个参数两个重载都可以调用,但lookup(Account&)匹配更精确
以上是关于共读Primer58.[6.5]参数匹配 Page217的主要内容,如果未能解决你的问题,请参考以下文章
共读Primer49.[6.3]返回类型和return语句--关于返回值 Page201