【编程笔记】虚函数表

如果一个C++类中包含有虚函数,C++编译器在进行编译时,会通过动态联编机制,为这个类生成一个“虚函数表”。
我们通常把所有的方法都是纯虚函数的类,叫做:接口类。

class BasicTable
{
public:
    virtual void Function1() = 0;
    virtual void Function2() = 0;
};

对于这个接口类里面方法的实现,需要编写一个子类继承于接口类:

class ChildTable : public BasicTable
{
public:
    void Function1()
    {
        printf("Function1.\n");
    };

    void Function2()
    {
        printf("Function2.\n");
    };
};

我们在调用的时候,就会涉及到虚函数表:

int _tmain(int argc, _TCHAR* argv[])
{
    BasicTable* pBT = new ChildTable;
    pBT->Function1();
    pBT->Function2();

    delete pBT;
    pBT = NULL;

    return 0;
}

那么指针pBT具体是怎么调用到子类的Function方法,我们来追踪下内存信息:
这里写图片描述
指针地址为:0x00429800,我们看下指针这块内存的信息:
这里写图片描述
其实这块内存的前4位字节就是虚函数表的指针地址,这里涉及到一个知识点:大端,小端的内存存储位置:
Intel X86体系结构的CPU使用Little Endian(小字节序)来存储数字。例如有一个数字为0x11223344,那么这个数据在内存中序列的顺序是44 33 22 11,即内存的低地址存放这个数字的低位。与此相对应的,还有Big Endia(大字节序),如PowerPC,所以数字0x11223344,在内存中的存储的序列为 11 22 33 44。
所以这块内存地址正确为:0x01245748,我们看下这块内存的信息:
这里写图片描述
我们在右边的信息,看到Function的方法,并且前4个字节0x012410a0就是Function1的地址,后4个字节0x01241140就是Function2的地址,我们确认下是不是:
通过Vs监视窗体可以详细看到:
这里写图片描述
通过一遍的跟踪,对虚函数表具体的信息,有了叫深的理解,我们直接模拟虚函数表的调用,写份代码:

class BasicTable
{
public:
    virtual void Function1() = 0;
    virtual void Function2() = 0;
};

class ChildTable : public BasicTable
{
public:
    void Function1()
    {
        printf("Function1.\n");
    };

    void Function2()
    {
        printf("Function2.\n");
    };
};

int _tmain(int argc, _TCHAR* argv[])
{
    BasicTable* pBT = new ChildTable;
    pBT->Function1();
    pBT->Function2();

    //!<获取虚函数表指针
    LPDWORD VtablePtr = (LPDWORD)(*((LPDWORD)pBT));
    //!<拿到Function方法的指针
    DWORD Fn_0 = *(VtablePtr + 0);
    DWORD Fn_1 = *(VtablePtr + 1);

    //!<函数类型声明
    typedef void(_stdcall* FUN)();
    FUN _Fun1 = (FUN)Fn_0;
    FUN _Fun2 = (FUN)Fn_1;

    //!<直接调用
    _Fun1();
    _Fun2();

    delete pBT;
    pBT = NULL;

    return 0;
}

输出:

Function1.
Function2.
Function1.
Function2.

结论:含有虚函数的C++类,它的对象的this指针所指向的地址即是虚函数表指针的所在。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值