//这里我不包含关于模板的详细匹配规则.
首先明白两个概念:
函数匹配:调用函数时,究竟调用哪一个重载函数。
二义性:错误情况,是指在调用重载函数时编译器不知道应该调用哪一个重载函数(有多个可选函数)。
函数的匹配过程如下:
1.确定候选函数:与被调函数同名的函数,并且在调用出这些函数在调用点是可见的。
2.选择可行函数:从候选函数中选择一个或者多个函数,这些函数都是可以被调用函数正确调用的。
关于可行函数的选择的规则如下:
1.形参数目应该等于或者大于(存在默认参数)实参个数。
void fun(int a, int b ,int c=20);
fun(10, 20);
fun(10, 20, 30);
2.实参可以通过隐式转换与对应的形参类型进行匹配。
void fun(int a);
char c = 'c';
fun(c);
3.确定最佳匹配项的可行函数:若有就调用她,否则出错。
下来我将一点一点的记录我所知的注意点。
首先在确定候选函数的时候:
我们应该注意,在局部域中的声明的函数会屏蔽外层作用域中的同名函数。
#include<iostream>
void test() {
std::cout << "啦啦啦" << std::endl;
}
void test(int differ) {
std::cout << "巴扎黑!" << std::endl;
}
namespace gdl {
void test(int *ptr) {}
void fun() {
//test(20);//error!!! 中不到匹配的函数.
}
}
====确定最佳匹配函数的方法====
1.首先明确一点:最佳匹配函数并不一定是完全匹配或者完美匹配的,只是说是可行函数中最佳匹配调用实参的。
最佳匹配的匹配次序(最佳到最差)依次为:完全匹配 - 通过提升转换实现的匹配 - 通过标准转换实现的匹配 - 通过类型转换实现的匹配
标准转换:
1.整形标准转换:如long->int, int -> short, ....
2.浮点型标准转换:double->float
3.整形与浮点型的相互转换
4.指针转换:任意指针到void*的转换,
5.bool转换:任意类型到bool型的转换
//标准转换,大概也就是说的标准类型之间的转换。不包含提升转换。
//然后值得注意的是:任何指针类型转换成void*的优先级高于装换为bool类型。
//且同为标准转换时没有谁优先于谁之说(exclude 上面一条。!!!)。
提升转换:
1.float到double的转换
2.char到int的转换, short到int的转换...boo->int
//提升转换也就是再同类型如同为整形,同为浮点型的情况下,类型提升的转换。
-------------
转换序列:
转换序列:实参到形参的转换往往需要经过多次转换,谓之转换序列。
转换序列一般由以下顺序构成:
1. 0次或一次的左值转换(包括左值到右值的转换,数组到指针的转换,函数到指针的转换)
2. 0次或者一次的(提升转换|标准转换),一般提升转换和标准转换不同时存在。
3. 0次或者1次的限定修饰转换
转换序列的等级:构成转换序列的最坏的等级。
void fun(int a);
float x = 10.0;
fun(x);
//在上面的转换中:
1.左值转换:提取x的值创建临时变量
2.标准转换:临时变量从float向int进行标准转换。
所以此次匹配中转换序列的等级为:标准转换
完全匹配:完全匹配形参和实参并不完全一致,完全匹配允许一些无关紧要的转换存在。
完全匹配所允许的无关紧要的转换如下:
1. 左值到右值的转换
2. 数组到指针的转换
3. 函数到指针的转换
4. 限定修饰转换,即const和非const, volatile和非volatile的转换
注意:底层const的const不能再转换中去掉const:
实参转换到形参:
const type* -> type*; //Error.
const type& -> type&; //Error.
左值到右值的转换:表示从左值表示的对象中抽取值得过程。
思考一下:左值到右值的转换存在的原因是否是:运算不能直接在内存之间发生?
然后简单地谈一谈const和volatile对最佳匹配等级的影响:
当同为完全匹配时,形参带const的优先级低于不带const的优先级
--------------------
void fun(int * pa);
void fun(const int * pa);
int a = 10;
fun(&a);
虽然连个重载函数同为完全匹配,但是由于const的存在导致fun(&a)的调用匹配的是void fun(int*);
//看起来也是挺合理的.
==============
1. 同为完全匹配,普通函数优先于模板函数或者特化的模板函数。
2. 当完全匹配函数只有模板函数时,模板函数的优先级更高
3. 看起来也很合理.
==========实例分析:
=============
1. void f(int a){}
2. void f(float a, float b= 3){}
3. void f(char a){}
4. void f(const char * a){}
5. void f(const char &a){}
//call.
char c= 'c';
f(c);
转换序列分析:
1. 左值转换 -> 提升转换
2. 左值转换 -> 标准转换
3. 完全匹配
4. 不能匹配,不在候选函数之列
5. 完全匹配,且const无影响
所以,此调用在3,5重载上存在二义性。