参数匹配
编译器根据当前范围内的函数声明与函数调用中提供的参数的最佳匹配,来选择要调用的重载函数。 如果找到合适的函数,则调用该函数。 合适具有下列含义之一:
找到完全匹配项。
已执行不重要的转换。
已执行整型提升。
已存在到所需自变量类型的标准转换。
已存在到所需参数类型的用户定义转换(转换运算符或构造函数)。
已找到省略号所表示的自变量。
此段描述来自,
https://learn.microsoft.com/zh-cn/cpp/cpp/function-overloading?view=msvc-170
隐式类型转换与重载确定
C++中,如果同时定义了多个函数名称相同,但函数签名不同的函数,则此行为称为函数重载。调用重载函数时,编译器将根据调用的参数数量与类型确定被调用的是哪一个函数,此过程称为重载确定。在重载确定过程中,如果编译器发现不止一个函数都是当前调用的最佳版本,则将引发二义性编译时错误。
重载确定是一个复杂的话题,下面只是提出了其中一些与隐式类型转换关联较大的,或具有代表性的话题进行论述;
首先,引用《C++ Primer》中对于重载确定的隐式类型转换等级的说明:
为了确定最佳匹配,编译器将实参类型到形参类型的转换划分成几个等级,具体排序如下所示:
1. 精确匹配,包括以下情况:
实参类型和形参类型相同
实参从数组类型或函数类型转换成对应的指针类型
向实参添加顶层const或从实参中删除顶层const
2. 通过const转换实现的匹配3. 通过类型提升实现的匹配4. 通过算术类型转换或指针转换实现的匹配5. 通过类类型转换实现的匹配
根据这段内容,我们可以得到以下要点:
数组向指针,以及函数向函数指针的隐式类型转换并不被C++视为隐式类型转换,其只是语法上的差别
显然,顶层const在不同变量之间不存在传递性
涉及底层const的类型转换被视为最接近精确匹配的隐式类型转换
类型提升优先于算术类型转换
自定义的类型转换等级最低,且各种自定义类型转换之间无先后差别
来看一个最简单的例子:
voidtest(int){}
voidtest(int, int = 0){}
intmain()
{
test(0); // 调用哪一个test?
}
上述代码中,我们仅通过一个int调用了test函数,此时,编译器无法确定调用的函数版本应该是void test(int)还是void test(int, int = 0),所以此调用是具有二义性的。