//重载第 3 步:确定最佳匹配函数void may(char);//原型#3char may(const char &);//原型#5
下面展开来说上述几条完全匹配时的规则 。
第 1 条:指向非 const
数据的指针和引用优先与形参为非 const
指针和引用的函数匹配,这一点需明确,const
和非 const
之间的区别只适用于指针和引用 。下面 4 个函数都与函数调用是完全匹配的:
//函数原型void recycle(int);//原型#1void recycle(const int);//原型#2void recycle(int &);//原型#3void recycle(const int &);//原型#4//函数调用int x = 5;recycle(x);//函数定义...
- 如果这 4 个函数同时存在,则无法完成重载,编译器会报多义性匹配的错误;
- 如果只存在函数
#1
与#2
,则无法完成重载 , 编译器会报重复定义的错误; - 如果只存在函数
#1
与#3
,则无法完成重载,编译器会报多义性匹配的错误; - 如果只存在函数
#1
与#4
,则无法完成重载,编译器会报多义性匹配的错误; - 如果只存在函数
#2
与#3
,则无法完成重载 , 编译器会报多义性匹配的错误; - 如果只存在函数
#2
与#4
,则无法完成重载,编译器会报多义性匹配的错误; - 如果只存在函数
#3
与#4
,则函数调用时编译器将会选择#3
。
第 3 条:同为模板函数时 , 优先与较具体的模板函数匹配,找出最具体的模板的规则被称为函数模板的部分排序规则(partial ordering rules) 。这意味着显式具体化优先于常规模板函数,都为常规模板函数时,编译器优先选择实例化时类型转换更少的那一个 。以下面的程序为例 , 调用方式
recycle(&ink)
既与模板 #1
匹配 , 此时 Type
将被解释为 blot *
,也与模板 #2
匹配,此时 Type
将被解释为 blot
,因此将这两个隐式实例 recycle<blot *>(blot *)
和 recycle<blot>(blot *)
发送到可行函数池中 。在选择最佳匹配函数时,#2
被认为是更具体的 , 因为它已经显式地指出,函数参数是指向 Type
的指针,相比于 #1
, 它对类型的要求更加地具体,在生成过程中所需要的转换更少,因此调用方式 recycle(&ink)
实际会匹配版本 #2
。//两个常规模板函数template <class Type> void recycle(Type t);//原型#1template <class Type> void recycle(Type * t); //原型#2//调用程序包含如下代码struct blot {int a; char b[10];};blot ink = {25, "spots"};...recycle(&ink);//使用版本#2//函数定义...
部分排序规则的另一个示例程序如下 , 它与上一个例子有异曲同工之妙 。由于模板 #2
做了特定的假设:数组内容是指针 , 对类型的要求更加地具体,因此在调用时第一个参数若传入指针数组 pt
, 则将实际匹配函数 #2
。//两个常规模板函数template <typename T>void ShowArray(T arr[], int n);//原型#1template <typename T>void ShowArray(T * arr[], int n); //原型#2//调用程序包含如下代码int things[6] = {13, 31, 103, 301, 310, 130};int * pt[3] = {&things[0], &things[2], &things[4]};ShowArray(things, 6);//使用版本#1ShowArray(pt, 3);//使用版本#2//函数定义...
将有多个参数的函数调用与有多个参数的原型进行匹配时,编译器必须考虑所有参数的匹配情况 。如果找到比其他可行函数都合适的函数,则选择该函数 。一个函数要比其他函数都合适,其所有参数的匹配程度都必须不比其他函数差,同时至少有一个参数的匹配程度比其他函数都高 。在有些情况下,可通过编写合适的函数调用,来引导编译器做出程序员期望的选择 。如下所示,其中模板函数返回两个值中较小的一个,非模板函数返回两个值中绝对值较小的那个 。第一次调用时根据重载解析策略选择了非模板函数
#2
;第二次调用时根据重载解析策略选择了模板函数 #1
的 double
版本 , 属于模板函数的隐式实例化;第三次调用的
推荐阅读
- 【番外篇】Rust环境搭建+基础开发入门+Rust与.NET6、C++的基础运算性能比较
- 【C++】spdlog光速入门,C++logger最简单最快的库
- 基于QT和C++实现的翻金币游戏
- 【C++】从零开始的CS:GO逆向分析3——写出一个透视
- 钩子 【pytest官方文档】解读-插件开发之hooks 函数
- C++ 使用栈求解中缀、后缀表达式的值
- <三>从编译器角度理解C++代码编译和链接原理
- Java 最长公共前缀
- windows C++ 异常调用栈简析
- Java Style的C++容器流式处理类