参考《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)
意味着用作实参的函数名和用作形参的函数指针只要返回类型和参数列表相同,就是匹配的 。实参类型形参类型
Type
Type &
Type &
Type
Type []
Type *
Type (argument-list)
Type (*) (argument-list)
Type
const Type
Type
volatile Type
Type *
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 步:确定最佳匹配函数 。通常,从最佳到最差的顺序如下所述:- 特征标完全匹配;
- 类型需经隐式提升转换,例如
char
和short
自动转换为int
,float
自动转换为double
; - 类型需经隐式标准转换,例如
int
转换为char
,long
转换为double
; - 类型需经隐式自定义转换,例如类中用户定义的类型转换 。
经验总结扩展阅读
- 【番外篇】Rust环境搭建+基础开发入门+Rust与.NET6、C++的基础运算性能比较
- 【C++】spdlog光速入门,C++logger最简单最快的库
- 基于QT和C++实现的翻金币游戏
- 【C++】从零开始的CS:GO逆向分析3——写出一个透视
- 钩子 【pytest官方文档】解读-插件开发之hooks 函数
- C++ 使用栈求解中缀、后缀表达式的值
- <三>从编译器角度理解C++代码编译和链接原理
- Java 最长公共前缀
- windows C++ 异常调用栈简析
- Java Style的C++容器流式处理类