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

    xiaoxiao2026-01-02  10

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

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

    我们有如下假定:函数调用以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函数。

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

    转载请注明原文地址: https://ju.6miu.com/read-1305586.html
    最新回复(0)