C++ 函数重载解析策略

参考《C++ Primer Plus》(第6版)中文版 , Stephen Prata 著,张海龙 袁国忠译,人民邮电出版社 。C++ 使用重载解析策略来决定为函数调用使用哪一个函数定义 。重载解析过程大致分为如下三步:

  • 第 1 步:创建候选函数列表 , 只要求函数名一样即可,对函数特征标以及是否为模板函数无要求;
  • 第 2 步:在上一步的基础上创建可行函数列表,包含特征标完全匹配的常规函数或模板函数、以及实参隐式转换后完全匹配的常规函数或模板函数,这些都是参数数目正确的函数;
  • 第 3 步:在上一步的基础上确定最佳匹配函数,若有则使用它,若没有则该函数调用失败 。
下面以一个例子来说明这个重载过程:
//全部函数原型void may(int);//原型#1float may(float, float = 3);//原型#2void may(char);//原型#3char * may(const char *);//原型#4char may(const char &);//原型#5template<class T> void may(const T &);//原型#6template<class T> void may(T *);//原型#7void may(char, double);//原型#8void mbk(float);//原型#9char mkk(int, char);//原型#10int mck(char);//原型#11double myk(float);//原型#12void mpk(char);//原型#13//函数调用may('B');//函数定义...重载第 1 步:创建候选函数列表 。即函数名称为 may 的常规函数和模板函数,候选函数列表如下:
//重载第1步:创建候选函数列表void may(int);//原型#1float may(float, float = 3);//原型#2void may(char);//原型#3char * may(const char *);//原型#4char may(const char &);//原型#5template<class T> void may(const T &);//原型#6template<class T> void may(T *);//原型#7void may(char, double);//原型#8重载第 2 步:创建可行函数列表 。由于整数类型 char 不能被隐式地转换为指针类型 char * , 因此函数 #4 和函数 #7 都被排除,而函数 #8 因为参数数目不匹配也会被排除 。进行完全匹配时,C++ 允许下表这些无关紧要的转换 , 表中 Type 表示任意类型,例如 char &const char & 的转换也包含在内,表中 Type (argument-list) 意味着用作实参的函数名和用作形参的函数指针只要返回类型和参数列表相同,就是匹配的 。
实参类型形参类型TypeType &Type &TypeType []Type *Type (argument-list)Type (*) (argument-list)Typeconst TypeTypevolatile TypeType *const Type *Type *volatile Type *根据此表可知,剩下的函数中包含特征标完全匹配的常规函数 #3#5、特征标完全匹配的模板函数 #6(此时 T 可以被实例化为 char)、实参隐式转换后完全匹配的常规函数 #1#2 。可行函数列表如下:
//重载第2步:创建可行函数列表void may(int);//原型#1float may(float, float = 3);//原型#2void may(char);//原型#3char may(const char &);//原型#5template<class T> void may(const T &);//原型#6重载第 3 步:确定最佳匹配函数 。通常,从最佳到最差的顺序如下所述:
  1. 特征标完全匹配;
  2. 类型需经隐式提升转换,例如 charshort 自动转换为 intfloat 自动转换为 double
  3. 类型需经隐式标准转换,例如 int 转换为 charlong 转换为 double
  4. 类型需经隐式自定义转换,例如类中用户定义的类型转换 。
依此规则 , 函数 #3 和函数 #5、函数 #6 都是特征标完全匹配的最佳匹配函数,函数 #1 需经隐式提升转换,函数 #2 需经隐式标准转换 , 由此各函数最佳匹配程度为:(#3, #5, #6) > #1 > #2 。当特征标完全匹配时,又有如下规则:
  • 指向非 const 数据的指针和引用优先与形参为非 const 指针和引用的函数匹配;
  • 优先与非模板函数匹配;
  • 同为模板函数时,优先与较具体的模板函数匹配 。
依此规则,非模板函数 #3#5 最佳匹配程度要高于模板函数 #6,即各函数最佳匹配程度为:(#3, #5) > #6 > #1 > #2 。最终出现了两个最佳匹配函数 #3#5,因此该函数调用失败 , 编译器将报错 。

推荐阅读