深入多态—虚表指针

来源:互联网 发布:淼说大数据精准营销 编辑:程序博客网 时间:2024/06/05 22:45

上一篇就多态做了简单的介绍,但还是对多态的运行很迷,那我们就来虚函数内部是怎么操作的?

(一)单继承中的虚函数(无虚拟继承)

#include<iostream>using namespace std;class A{public:    virtual void Funtest1()    {        cout<<"A::Funtest1()"<<endl;    }    virtual void Funtest2()    {        cout<<"A::Funtest2()"<<endl;    }    int _a;};class B:public A{public:    virtual void  Funtest1()//实现函数重写    {        cout<<"B::Funtest1()"<<endl;    }    virtual void FunTest3()    {        cout<<"B::FunTest3()"<<endl;    }    int _b;};void Fun(){    cout<<sizeof(B)<<endl; //12    A a;    B b;    a._a=1;    b._a=2;    b._b=3;}int main(){    Fun();    system("pause");    return 0;}

分析如下:

这里写图片描述
这里写图片描述
注:单继承通常通过在每个对象内包含一个vptr指针来实现虚拟函数,vptr指针指向一个叫做vtbl的函数指针向量(称为虚拟函数表,也叫V表)。虚函数按照其声明顺序存在于虚表中。

为了验证我们上面所分析的准确无误,下面定义一个Printv函数,打印虚表所指向的函数~
typedef void (*pFunc)();//定义一个函数指针类型
其中void (*pFunc)();//是函数指针变量

typedef void (*pFunc)();void Printv(A& a)//用来打印虚表所指向的函数{    pFunc* c=(pFunc*)(*(int*)&a);  //定义一个函数指针    while(*c)    {        (*c)();        c++;    }}

运行结果:
这里写图片描述
说明前面的分析无误
(二)单继承中的虚函数(有虚拟继承)

using namespace std;typedef void (*pFunc)();class A{public:    virtual void Funtest1()    {        cout<<"A::Funtest1()"<<endl;    }    virtual void Funtest2()    {        cout<<"A::Funtest2()"<<endl;    }    int _a;};class B:virtual public A{public:    virtual void  Funtest1()//实现函数重写    {        cout<<"B::Funtest1()"<<endl;    }    virtual void FunTest3()    {        cout<<"B::FunTest3()"<<endl;    }    int _b;};void Printv(B& b){    pFunc* c=(pFunc*)(*(int*)&b);    while(*c)    {        (*c)();        c++;    }}void Fun(){    cout<<sizeof(B)<<endl;//20  为什么呢?    A a;    B b;    a._a=1;    b._a=2;    b._b=3;    Printv(b);}int main(){    Fun();    system("pause");    return 0;}为什么只加了个虚拟继承,派生类的大小就变成了20呢?看内存观变化:

这里写图片描述
这里写图片描述
(三)多继承(无虚拟继承)

class A{public:    virtual void Funtest1()    {        cout<<"A::Funtest1()"<<endl;    }    virtual void Funtest2()    {        cout<<"A::Funtest2()"<<endl;    }    int _a;};class B{public:    virtual void FunTest3()    {        cout<<"B::FunTest3()"<<endl;    }    virtual void FunTest4()    {        cout<<"B::FunTest4()"<<endl;    }    int _b;};class C: public A, public B{public:    virtual void  Funtest1()//实现函数重写    {        cout<<"C::Funtest1()"<<endl;    }    virtual void FunTest3()    {        cout<<"C::FunTest3()"<<endl;    }    virtual void FunTest5()    {        cout<<"C::FunTest5()"<<endl;    }    int _c;};void Fun(){    cout<<sizeof(C)<<endl;    A a;    B b;    C c;    a._a=1;    b._b=2;    c._a=3;    c._b=4;    c._c=5;}int main(){    Fun();    system("pause");    return 0;}

派生类内存分布:
这里写图片描述
(四)菱形继承

using namespace std;typedef void (*pFunc)();class A{public:    virtual void Funtest1()    {        cout<<"A::Funtest1()"<<endl;    }    virtual void Funtest2()    {        cout<<"A::Funtest2()"<<endl;    }    int _a;};class B:virtual public A{public:    virtual void FunTest1()    {        cout<<"B::FunTest1()"<<endl;    }    virtual void FunTest3()    {        cout<<"B::FunTest3()"<<endl;    }    int _b;};class C:virtual  public A{public:    virtual void  Funtest2()//实现函数重写    {        cout<<"C::Funtest2()"<<endl;    }    virtual void FunTest4()    {        cout<<"C::FunTest4()"<<endl;    }    int _c;};class D: public B,public C{public:    virtual void  Funtest1()//实现函数重写    {        cout<<"D::Funtest1()"<<endl;    }    virtual void FunTest3()    {        cout<<"D::FunTest3()"<<endl;    }    virtual void FunTest4()    {        cout<<"D::FunTest4()"<<endl;    }    virtual void FunTest5()    {        cout<<"D::FunTest5()"<<endl;    }    int _d;};void Fun(){    cout<<sizeof(D)<<endl; //36   具体为什么看图解    D d;    d._a=1;    d._b=2;    d._c=3;    d._d=4;}int main(){    Fun();    system("pause");    return 0;}

D模型分析
这里写图片描述

原创粉丝点击