C++函数查找的一般性规律(一)

来源:互联网 发布:html 展示json数据 编辑:程序博客网 时间:2024/05/29 21:30

c++中函数查找的一般规律


c++中对于同名函数存在三种情况:重载、覆盖(重写)和隐藏。由于存在这三种同名函数似的对同名函数查找显得让人迷惑。最近

看了狄泰软件学院的C++视频结合自己看书,对此有一点心得,总结一下。

首先对于这三种情况的后两种情况属于继承关系中的同名函数查找问题,相较于第一种要复杂一些,但是他们共同遵循的前提规则就

先查找名字再进行类型检查。下面将对重载函数查找的一般规律进行说明。


首先对于同一作用域的所有函数的名称进行检查,找到所有与调用的函数同名的函数作为候选函数,这一步是名字查找。

接下来的几步都是类型检查

然后对所有的候选函数进行初步类型检查,此时就是检查形参个数,类型是否与实参匹配,此处的匹配包含一下几种情况:

1)形参与实参完全匹配

2)实参可以类型转换为形参

3)形参中存在默认实参,此时已经给定的实参有可能是上述两种中的任何一个,并且此时实参个数小于形参个数

经过上述筛选就从后患函数中选择出了可行函数,当然也有可能没有可行函数,此时编译器会报错,提示无法匹配,这也是函数匹配

失败的一种情况,假如存在可行函数,那么最终的函数就可能是从这些可行函数中选择

最后一步就是在可行函数中寻找最佳匹配(假如存在),此处最佳匹配的标准是:实参类型与形参类型越接近,他们就匹配的最好。

最好的一种情况就是形参与实参类型完全一样,次优的就是可以类型转换或者存在默认实参。这一步也有可能失败,出现多个匹配即

二义性,这是函数匹配失败的第二种情况

以下举例说明:

例1:

类定义如下:

#include <iostream>#include <string>using namespace std;class Test{   public:    Test()    {        cout << "Test()" << endl;      }    void display()    {        cout << "display()" << endl;    }void display(int x)    {        cout << "display(int x)" << endl;    }void display(double x)    {        cout << "display(int x)" << endl;    }};

考虑如下代码:

int main(){       Test test;     test.display();     test.display(2);      test.display(2.4);     return 0;}
输出结果如下:

display()

display(intx)

display(doublex)


分析:(以test.display(2);为例说明)首先当调用名为display的函数时,先在类的作用域中进行函数名称查找,发现一共找到三个名称符合的函数,他们分别是voiddisplay()voiddisplay(int x)voiddisplay(double x)。即候选函数,接下来就是参数检查的第一步,在这里我们的实参是int型,那么首先排除voiddisplay(),因为它的形参列表为空,然后就是剩余的两个函数,此时两个均符合初步的类型检查,即可行函数,首先voiddisplay(int x)的形参与我们的实参个数,类型完全一致,符合条件1,而voiddisplay(double x)之所以符合初步类型检查是因为int可以隐式类型转换为double,符合条件2

最后一步就是最佳匹配了,这一步我们最终选择了voiddisplay(int x),原因就是,这是上面提到的最好的一种前情况,完全匹配,而voiddisplay(double x)还要进行一步类型转换,因此被舍弃。剩余的两个函数调用也是这种过程,就不再一一分析。


2

类定义如下:

#include <iostream>#include <string>using namespace std;class Test{   public:    Test()    {    }    void display()    {        cout << "display()" << endl;    }void display(int x)    {        cout << "display(int x)" << endl;    }void display(int x,int y =0){cout << "display(int x,int y =0)" << endl;}};

考虑如下代码:

int main(){Test test;test.display(2);return 0;}

发现编译无法通过,错误提示如下:

cz.cpp:In function ‘int main()’:

cz.cpp:34:16:error: call of overloaded ‘display(int)’ is ambiguous

test.display(2);

^

cz.cpp:34:16:note: candidates are:

cz.cpp:17:7:note: void Test::display(int)

voiddisplay(int x)

^

cz.cpp:22:7:note: void Test::display(int, int)

voiddisplay(int x,int y =0)


错误提示的意思就是说出现多个函数符合条件,即出现二义性。

接下来进行分析:首先第一步仍然是函数名称查找,此时四个函数全部符合,属于候选函数,接下来的初步类型检查中,voiddisplay()被排除,其余两个均符合三个条件中的某一条因此全部属于可行函数,此时并没有任何错误,之所以出现错误就是出现在最后的最佳匹配阶段,此时由于voiddisplay(int,int)函数的第二个参数是默认实参,所以在参数匹配是不检查此参数,而第一个参数同display(int)的参数类型完全一样,就出现了两个最好的匹配结果,出现二义性,所以匹配失败。

小结:

函数匹配原则:先查找名字再进行类型检查

重载函数匹配失败的情况:1)找不到符合情况的函数;2)出现多个匹配的函数,即二义性

以上是我关于重载函数匹配的一点理解,若有错误,请批评指正,谢谢。











0 0