详解重载解析(一)

来源:互联网 发布:怎么在淘宝上开充值店 编辑:程序博客网 时间:2024/05/16 07:50

一.前言

什么是重载解析呢? 我们要解释重载解析就要先了解重载。当我们对同一个函数名写了不同参数列表的版本之后,编译器会生成这个函数的不同重载版本。那么当我们调用这个函数的时候,编译器就会子自动根据实参的参数类型来判断到底调用的是哪个版本的函数。那么编译器选取最合适的函数版本的这一个过程就被称为重载解析。

二.重载解析的步骤

在这里我们先不忙考虑含有模板函数的情况,这个问题我们留到下一章来讨论。当没有模板函数的情况下。当我们调用一个函数的时候,编译器会做出如下几个事情:

  • 选定本次调用对应的重载函数集,集合中的函数被称为 候选函数。候选函数具有两个特征:
    • 与被调用的函数同名。
    • 其声明在调用点可见。
  • 考察本次调用的提供实参,然后从候选函数中选出能被这组实参调用的函数,这些新选出来的函数被称为 可行函数。可行函数也有两个特征:
    • 一是其形参数量与本次调用提供的实参数量相等。
    • 二是每个实参类型于对应类型形参类型相同或者是能够通过隐式转换匹配。
  • 从可行函数中选择与本次调用最匹配的函数,这一个过程中,逐一检查函数调用提供的实参,寻找形参类型与实参类型最匹配的那个可行函数。如何被称为最匹配呢?一会儿我们再来详解。
  • 如果函数有多个参数呢?如何来确定最佳匹配呢?,先我们提出这个问题,放到后面来讲。


三.最佳匹配

在这里我们定义两个等级的匹配:(T 表示任意类型)

  • 等级一: 精确类型匹配、T -> const T、数组和函数转化为对应的指针、T* const -> T*,T->T&
  • 等级二: 类型提升,T& -> const T& ,内置类型转换 , T* -> const T* 、 T* -> void* 、类型转换实现匹配。

等级一可以看做是成功匹配,等级二可以看做是转换匹配。
当然优先级也是等级一高,等级二次之,同等级的优先级也是从左到右依次降低。

值得注意的是如果两个重载函数的对应形参的转换是等级一之间的转换,那么这两个重载函数版本是具有二义性的。例如:

  • void function(int) && void function(const int)
  • void function(int,int* const) && void function(const int ,int*)

如果是等级二之间的转换就会按照优先级先后进行匹配。

 假如有:         class A         {           public:              A(short){}          }
  • void fun(int) && void fun(float) && void fun(A)
  • 对于以上三个函数当实参类型为short时优先级从左到右依次降低。


四.多形参匹配顺序

对于多参数的函数重载解析,编译器会依次检查每个实参确定哪个函数是最佳匹配,如果有且只有一个函数满足下列条件,则匹配成功:

  • 该函数的每个实参的匹配优先级都不低于其他可行函数的匹配。(等级一所有的转换可以看做同优先级)
  • 该函数至少有一个实参的匹配优先级要高于其他任何可行函数提供的匹配。(等级一所有的转换可以看做同优先级)


五.尾语

当我们在写程序的时候我们应该尽量避免这样容易产生歧义的函数重载。当然,我们似乎可以通过强制类型转换来使得其中一个实参实现对某个重载版本的匹配。但是在良好的设计当中,不应该对实参进行强制类型转换。在调用重载函数时应该尽量避免强制类型转换。如果在实际应用过程中确实需要强制类型转换,则说明我们设计的形参集合不合理。

下篇文章将会介绍,如果在有模板函数的情况下,重载解析又多了哪些步骤。

0 0
原创粉丝点击