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

来源:互联网 发布:足球彩票分析软件 编辑:程序博客网 时间:2024/05/16 05:40

上一篇文章中对重载函数的函数查找规律进行说明,这篇文章将会对重写情况进行说明,重写发生

在类的继承过程中,今天将说明重写的函数调用过程

我们有如下假定:函数调用以p->func()p.func()的形式调用,则主要分为如下四个步骤:

1)首先确定p的静态类型,只有静态类型是类类型,那么我们才能调用成员,并且静态类型决定了哪些成员是可见的。

2)p对应的静态类型对应的类中查找func。如果找不到,则一次在直接基类中查找直到到达继承链的顶端。若仍然找

不到名为func的函数,则编译器将报错。这一步可以认为是重载中的候选函数的确定。

3)一旦找到了func,就进行常规的类型检查以确认本次找到的func,对于本次调用是否合法。这一步可以看作是重载中

后两步的集合。

4)假设第三步中调用合法,那么编译器蒋根据调用的是否时虚函数而产生不同的代码:

1>如果func是虚函数并且我们是通过应用或者指针进行的调用,则编译器产生的代码将在运行是确定到底运行该虚函

数的哪个版本(基类还是派生类),选择的依据是动态类型。

2>如果func不是虚函数,或者我们是通过对象进行的调用,则编译器将会产生一个常规函数调用的代码,即根据静态

类型进行函数调用。

类定义如下:

class Parent{public: Parent () {cout<<"Parent"<<endl;}~ Parent () {cout<<"~Parent"<<endl;}virtual void vDis(){cout<<"Parent::virtual void vDis()"<<endl;}};class Child:public Parent{public:Child(){cout<<"Child"<<endl;}~Child(){cout<<"~Child"<<endl;}void vDis(){cout<<"Child::void vDis()"<<endl;}};

考虑如下代码:

int main(){Child c1;Parent *p1=&c1;p1->vDis();c1.vDis();return 0;}

输出结果如下:

Parent

Child

Child::voidvDis()

Child::voidvDis()

~Child

~Parent

结果分析:

在进行p1->vDis();函数调用时首先确定p1的静态类型即Parent类,然后在Parent类中查找vDis(),发现刚好有这个函数,

然后进行第三部发现调用合法,重点在第四步,此时vDis是虚函数,并且vDis是通过指针p1进行调用,所以要在运行

是确定到底调用哪个版本,依据是动态类型,p1的动态类型是Child类型,因此调用Child版本的vDis函数。

c1.vDis();的前三步和前一个相同,我们分析第四步,此时vDis是虚函数,但是我们是通过对象调用,因此会根据静

态类型调用,即调用ChildvDis函数。


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


0 0