关于虚表和虚表指针

来源:互联网 发布:摄影美工 编辑:程序博客网 时间:2024/06/08 03:47

有关知识复习

1:动态多态
动态绑定:在程序执行期间(非编译期间)判断所引用对象的实际类型,根据其实际类型调用相应的方法。
2:动态多态具体实现、

class A{public:    virtual void funtest1()    {        cout << "A.funtest1" << endl;    }    virtual void funtest2()    {        cout << "A.funtest2 " << endl;    }    int _a;};class B1 : public A{public:    virtual void funtest1()    {        cout << "B1.funtest1" << endl;    }    virtual void funtest3()    {        cout << "B1.funtest3" << endl;    }    int _b1;};void funtest(A &s){    s.funtest1();    s.funtest2();}int main(){    B1 b1;    funtest(b1);    system("pause");    return 0;}

在funtest函数里面用基类的引用作为参数,真正传过去的是派生类的对象,而且在派生类里面是对funtest1函数进行了重写的,所以在执行期间会根据所引用的具体类型调用相应的函数。
这里写图片描述
3:虚表的简单查看

#include<stdlib.h>#include<stdio.h>#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 B1 : public A{public:    virtual void funtest1()    {        cout << "B1.funtest1" << endl;    }    virtual void funtest3()    {        cout << "B1.funtest3" << endl;    }    int _b1;};typedef void(*pvf)();void Print()     {    B1 b1;    b1._a = 1;    b1._b1 = 2;    pvf *fun = (pvf *)*(int*)&b1;       while (*fun)    {        (*fun)();             fun++;    }}void FunTest(){    cout << sizeof(B1) << endl;}int main(){    Print();    FunTest();    system("pause");    return 0;}

这里写图片描述
通过求取B1类的大小可以在内存中查看b1的存储方式,图上所表示的是虚表指针指向的虚表和打印出来的虚表的实际对应.通过对b1对象内存的分析可以知道除了b1所含的两个整型意外,最上面的四个字节就是虚表指针,指向的虚表通过打印的方式显示出来如图中所示,由于B1对A类是公有继承而且在B1类中对基类的funtest1函数进行了重写,所以派生类B1的虚表就应该是图中所显示的内容。

菱形虚拟继承中派生类的虚表指针以及偏移量指针

class A{public:    virtual void funtest1()    {        cout << "A.funtest1" << endl;    }    virtual void funtest2()    {        cout << "A.funtest2 " << endl;    }    int _a;};class B1 :virtual public A{public:    virtual void funtest1()    {        cout << "B1.funtest1" << endl;    }    virtual void funtest3()    {        cout << "B1.funtest3" << endl;    }    int _b1;};class B2 :virtual public A{public:    virtual void funtest2()    {        cout << "B2.funtest2" << endl;    }    virtual void funtest4()    {        cout << "B2.funtest4" << endl;    }    int _b2;};class  C :public B1, public B2{public:    virtual void funtest3()    {        cout << "C.funtest3" << endl;    }    virtual void funtest4()    {        cout << "C.funtest4" << endl;    }    virtual void funtest5()    {        cout << "C.funtest5" << endl;    }    int _c;};typedef void(*pvf)();void Print()     {        A a;    /*c._a = 1;    c._b1 = 2;    c._b2 = 3;    c._c = 4;*/    pvf *fun = (pvf *)*(int*)&a;       while (*fun)    {        (*fun)();             fun++;    }}void FunTest(){    cout << sizeof(C) << endl;}int main(){    Print();    FunTest();    system("pause");    return 0;}

这里写图片描述
如图所示,就是C类对象在内存空间的具体存储,红色线所指函数或者数字即为C类对象中的指针所指内容,要么是偏移量大小,要么是虚表指针,特别之处在于两个 ‘-4’,表示的是从该位置向上偏移四个字节才是C通过这个继承体系继承的B1,B2 类在C中存储的起始位置。12和24就是偏移量大小,若C B1 B2需要访问基类成员所需要偏移的字节数。

0 0
原创粉丝点击