关于虚表和虚表指针

有关知识复习

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
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值