手机代码网站有哪些问题吗方象科技服务案例
本篇将介绍C++函数重载的概念,及重载决议规则。
一、函数重载
同一作用域内,函数名相同,而形参列表不同的函数称之为重载函数(overloaded function)。
需要特别注意:以下情况看似形参列表不同,实则等价,无法形成函数重载。
// 1. 声明中有无形参名无法形成重载
void test1(int &arg);
void test1(int &); // 二者等价// 2. 类型别名无法形成重载
using count = int&;
void test2(int &);
void test2(count); // 二者等价// 3. 顶层const无法形成重载
void test3(const int);
void test3(int); // 二者等价void test3_(int *const);
void test3_(int *); // 二者等价// √ 底层const就可以形成重载
void test4(const int&);
void test4(int &); // 有效重载void test4(const int*);
void test4(int *); // 有效重载
此外,函数重载必须发生在同一作用域内。内部作用域中的函数会覆盖外部同名函数的名字,在下面的重载决议步骤中可以看到,名字被覆盖将直接导致外部函数重载失效。
二、重载决议
对于一个函数调用而言,如果该函数名对应了一组重载函数,则根据实参将函数调用与某一个重载函数绑定起来,这一过程称之为函数匹配(function matching),也叫做重载决议(function resolution)。
重载决议的过程可以划分为以下三步,前两步的失败会导致无匹配错误(no matching),最后一步的失败会导致二义性调用(ambiguous call)错误。
第一步:确定候选函数
满足下列条件称之为候选函数candidate function
:
- 与被调用函数同名
- 声明在调用点可见
第二步:确定可行函数
满足下列条件称之为可行函数viable function
:
- 形参与提供实参的数量相等
- 每个实参的类型与形参类型对应匹配
第三步:寻找最佳匹配
与实参类型最匹配的那个可行函数,称之为最佳匹配。
其基本思想是实参类型与形参类型越接近,匹配的越好。最佳匹配函数需要满足以下两条要求:
- 该函数每个实参的匹配都不劣于其他可行函数需要的匹配
- 至少有一个实参的匹配优于其他函数提供的匹配
如果可行函数中没有选项能够满足上述两个条件,则该函数调用将被判定为二义性调用并引发编译器报错。
实参类型转换下的匹配优先级划分
在第三步中,为了确定最佳匹配,下列规则中越靠前的情况,则当前参数的匹配优先度越高。即第三步中所描述的匹配的优劣。
- 精确匹配
- 实参与形参类型相同、
- 实参从数组类型或函数类型转换为相应类型的指针
- 向实参添加或删除顶层const
- const转换实现的匹配(关于和精确匹配第三条的不同点,在最后赘述)
- 类型提升实现的匹配
- 算术类型转换或指针转换实现的匹配
- 类类型转换实现的匹配
向实参添加或删除顶层const
与const转换实现的匹配
这两种情况的不同之处:
前者指的是,形参与实参顶层const类型不同。
void test(const int);const int i = 1;
int j = 2;
test(i);
test(j); // 都是精确匹配
而后者指的是,形参具备底层const,实参不具备底层const。此时实参将会被加上const限定。这种情况的优先级逊于精确匹配。
void test(const int&);
void test(int &);const int i = 1;
int j = 2;
test(5); // 字面值,会匹配到test(const int&)
test(i); // 会匹配到test(const int&)
test(j); // 会匹配到test(int &)