重载解析

来源:互联网 发布:Linux隐藏服务器lp 编辑:程序博客网 时间:2024/06/04 19:20

    重载解析是一个过程,它根据所给定的表达式,来选择进行调用的函数。

    重载解析规则的大多数概念都是很简单的,但在C++标准化过程中,一些细节会变得非常复杂。复杂性主要是为了支持现实中的一些例子。这些例子从主观上看起来应该具有“明显的最佳匹配”,但当试图形式化这种主观匹配时,却会遇到各种各样的困难。

1.何时应用重载解析?

    重载解析可以看成是:函数调用整个完整处理过程的一部分。

    事实上,也并不是所有的函数调用都会涉及到重载解析。1)如果通过函数指针或者成员函数指针进行调用,就不会进行重载解析;因为究竟调用哪个函数是在运行期由指针来决定的。 2)类似函数的宏不能被重载,即不会进行重载解析

   从较高的抽象层次来看,对于一个命名函数的调用,通常会使用以下的处理方法:

  •  查找名称,从而形成一个初始的重载集合
  • 如果有必要的话,会用各种方法对这个集合进行修改
  • 任何与调用不匹配的候选函数从重载集合中删除,最后得到的集合就是:可行的候选函数集
  • 执行重载解析来寻找一个最佳候选函数,如果能够找到,则选择这个最佳候选函数,否则这个调用就具有二义性
  • 检查这个被选定的最佳候选函数,例如:如果它是不能访问的私有成员,便会出错,此时调用失败

2.简化过的重载解析

       重载解析通过比较调用实参和候选函数参数的匹配程度,来对所有的可行候选函数进行分级。对于匹配级别高的候选函数,它的每个参数的匹配程度都不能低于匹配级别低的候选函数的相应参数的匹配程度。

eg:

    void combine(int,double);

    void combine(long,int);

   int main()

  {

       combine(1,2);

  }

    在该例子中,combine的调用具有二义性。第一个候选函数可以最佳匹配第一个参数,第二个候选函数可以最佳匹配第二个参数。我们可能会觉得,从某种意义上而言,int和long的相似度要比int与double相似度更高,但是C++并不会试图度量这种涉及到多个调用实参的相似度,从而引发二义性。

    根据分级的原则,我们需要指出调用实参和候选函数相应实参的匹配程度。从近似的角度出发,对下面匹配进行分级:(从最佳匹配到最差匹配)

  • 完美匹配:参数的类型与实参的类型相同,或者参数的类型是指向实参类型的引用
  • 有细微调整的匹配:例如数组decay为指向数组第一个元素的指针
  • 发生提升的匹配:提升是一种隐式类型转换,它包含把占位少的整数类型转换为占位多的类型(bool,short,char)---》(int,unsigned int ,long, unsigned long)
  • 发生标准转型的匹配:这包含任何种类的标准转型,如int到float
  • 用户自定义转型的匹配:这允许任何种类的隐式类型转换
  • 和省略号的匹配:省略号可以匹配任何类型

注意:对函数而言,针对两种类型的引用进行重载是很普遍的

eg:void report(int&);               (1)

        void report(int const&);     (2)

int main()

{

      for(int k=0;k<10;++k)

              report(k);   //调用(1)

     report(42);    //调用(2)

}

  如果实参是个左值,那么将会优先考虑没有const的版本,而对于作为右值的实参,将会优先考虑const的版本

总而言之:

  • 对于T类型的右值,T和T const&的匹配程度是一样的
  • 对于T类型的左值,T和T &的匹配程度是一样的

3.重载的细节

  • 非模板优先

                      当重载解析的其他各个方面都是等同的时候,非模板函数将会优先于由模板产生的实例

                      如果这种选择是在两个模板之间进行的,那么将会选择特化程度较高的模板

  • 转型序列:如果转型序列A是转型序列B的子序列,那么将会优先使用A对应的转型序列
  • 指针的转型
  • 仿函数和代理函数

                        在查找完函数名称、建立一个初始化重载集之后,这个集合还会发生某些变化。当调用表达式引用的是一个类对象,而不是一个函数,就会向重载集中添加两种函数: 

     1)把任何operator()都添加到重载集中,具有这个运算符的对象通常被称为仿函数

     2)某个class类型对象包含一个到函数类型指针的转型运算符,这种情况下,就会把一个代理函数添加到重载集中。值得注意的是:这个候选的代理函数除了具有显式声明的参数之外,还具有一个隐含参数,隐含参数的类型是转 型函数所指派的类型







原创粉丝点击