函数匹配

通常情况下是很容易确定某次调用应该选择哪个重载函数,但是当几个重载函数的形参数量相等以及形参的类型可以由其它类型转换得来时,此时选择哪个重载函数就不那么容易。

确定候选函数和可行函数

  • 函数匹配的第一步就是选定本次调用对应的重载函数集,集合中的函数称为候选函数,候选函数的两个特征:
    • 被调用的函数同名。
    • 声明在调用点可见。
  • 考察本次调用的实参,然后从候选函数中选出能被这组实参调用的函数,这些新选出的函数称为可行函数,如果找不到可行函数,编译器将会报无匹配函数的错误。可行函数的两个特征:
    • 形参数量与本次调用提供的实参数量相等。
    • 每个实参的类型与对应的形参类型相同,或者能够转换成形参类型。
  • 寻找最佳匹配(如果存在)
    • 从可行函数中选择与本次调用最匹配的函数,实参与形参的类型越接近,它们匹配的越好。

含有多个形参的函数匹配

void f(int,int);
void f(double,double);

f(10,3,14);

f(int,int)f(double,double) 都是可行函数,编译器将依次检查每个实参以确定哪个函数是最佳匹配,如果有且仅有一个函数满足下列条件,则匹配成功:

  • 该函数的每个实参的匹配都不劣于其他可行函数需要的匹配。
  • 至少有一个实参的匹配优于其他可行函数提供的匹配。

如果在检查了所有的可行函数之后,没有一个函数脱颖而出,则调用是错误的,编译器将报二义性调用信息,上面的例子就是这种情况。

实参类型转换

实参类型到形参类型转换的等级:

  • 精确匹配,包含以下情况
    • 实参和形参类型相同。
    • 实参从数组类型转换成对应的指针类型。
    • 向实参添加顶层 const 或者从实参中删除顶层 const
  • 通过const 转换实现的匹配。
  • 通过类型提升实现的匹配。
  • 通过算术转换或者指针转换实现的匹配。
  • 通过类类型转换实现的匹配。

需要类型提升和算术类型转换的匹配

小整型一般都会提升到int 类型或者更大的整数类型:

void f(int);
void f(short);

f('a');// char 将被提升为int,调用int

所有的算术转换级别都一样,例如把 int 转换成 unsigned int 并不比把 int 转换成 double 更高级:

void f(float);
void f(long);

f(3.14);// 字面值3.14是double,既可以转换long也可以转换成float,存在二义性

函数匹配和const实参

如果重载的区别在于它们的引用类型的形参是否引用了 const,或者指针类型的形参是否指向 const,当调用发生时编译器通过实参是否是常量决定调用哪个函数:

void f(const int&);
void f(int&);

const int a =1;
int b =2;
f(a); //调用f(const int&)
f(b); //调用f(int&)

指针类型的形参也类似,如果两个函数的唯一区别是它的指针形参指向常量或非常量,则编译器能通过实参是否是常量决定调用哪个函数。

原文地址:https://www.cnblogs.com/xiaojianliu/p/12498138.html