虚函数备忘

把关于虚函数不清楚的地方小测试了下,记录下来,备忘

测试编译器:mingw32-gcc-3.4.5

struct A{    virtual void f1(){        std::cout<<"A::f1"<<std::endl;    }    virtual void f2(){        std::cout<<"A::f2"<<std::endl;    }    void f3(){        std::cout<<"A::f3"<<std::endl;    }};struct B:A{    void f1(){        std::cout<<"B::f1"<<std::endl;    }    virtual void f2(){        std::cout<<"B::f2"<<std::endl;    }    void f3(int){        std::cout<<"B::f3"<<std::endl;    }};void vf_test(){    A a;    B b;    //now, p1 point to a B instance, "*p1" object's vpointer point to B's vtable    A *p1=new B;    //ok, p1 is A's pointer, so it calls none virtual function A::f3()    p1->f3();    //compile time error, notice that the member functions have the same name as the derived-class's will be rewrite.    //so, B::f3(int) hides A::f3()    //b.f3();    //calls A::f1()    (*p1).A::f1();    //calls B::f1()    (*p1).f1();    //calls B::f2()    (*p1).f2();    //(A(*p1)).f1() and (A(*p1)).f2() symbols will be linked to A's member function.    (A(*p1)).f1();    (A(*p1)).f2();    //but, notice that "*p1" object's vpointer point to B's vtable    //so, after type casting, "*p1" object's vpointer looks like already point to A's vtable at runtime    //let's take a test about it    //A's and B's object only have a vpointer of 4 bytes    std::cout<<"size of A is "<<sizeof(A)<<std::endl;    std::cout<<"size of B is "<<sizeof(B)<<std::endl;    std::cout<<"virtual pointer's value of type A is "<<*(unsigned long*)(&a)<<std::endl;    std::cout<<"virtual pointer's value of type B is "<<*(unsigned long*)(&b)<<std::endl;    std::cout<<"virtual pointer's value of p1 is "<<*(unsigned long*)p1<<std::endl;    std::cout<<"virtual pointer's value of &A(*p1) is "<<*(unsigned long*)(&(A(*p1)))<<std::endl;    delete p1;}

output:

A::f3

A::f1

B::f1

B::f2

A::f1

A::f2

size of A is 4

size of B is 4

virtual pointer's value of type A is 4508528

virtual pointer's value of type B is 4508544

virtual pointer's value of p1 is 4508544

virtual pointer's value of &A(*p1) is 4508528

这个测试主要是说明虚表指针的运行时切换问题,关于虚函数与类的作用域的较详细解释可参见《C++ Primer 4th Edition》15.5.4, 特别要注意派生类成员名字屏蔽基类成员名字的问题,这里只摘录其中一段对于继承体系中名字查找的小结供大家参考:

  • 关键概念:名字查找与继承;理解c++中继承的关键在于理解如何确定函数调用。确定函数调用遵循以下四个步骤:

    1. 首先确定进行函数调用的对象、引用或指针的静态类型。
    2. 在该类中查找函数,如果找不到,就在直接基类中查找,如此循着类的继承链往上找,直到找到该函数或者查找完最后一个类。如果不能在类或其相关基类中找到该名字,则调用是错误的。
    3. 一旦找到了该名字,就进行常规类型检查,查看如果给定找到的定义,该函数调用是否合法。
    4. 假定函数调用合法,编译器就生产代码。如果函数是虚函数且通过引用或指针调用,则编译器生成代码以确定根据对象的动态类型运行哪个函数版本,否则,编译器生成代码直接调用函数。

  • 原文链接: https://www.cnblogs.com/tnt_vampire/archive/2010/05/15/1736240.html

    欢迎关注

    微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍

    原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/10889

    非原创文章文中已经注明原地址,如有侵权,联系删除

    关注公众号【高性能架构探索】,第一时间获取最新文章

    转载文章受原作者版权保护。转载请注明原作者出处!

    (0)
    上一篇 2023年2月7日 上午12:27
    下一篇 2023年2月7日 上午12:29

    相关推荐