C++虚表和虚函数--一目了然

本文通过代码示例展示了C++中虚表的存储结构和虚函数的调用方式。程序创建了一个具有多重继承和虚函数的类,并通过指针访问虚表来直接调用虚函数,揭示了虚表在多继承下的组织形式以及虚函数的实现原理。

直接上代码

#include <iostream>
using namespace std;

class TestVirPtr0
{
public:
    virtual void FirPrint0(void) {
        cout << "TestVirPtr0->FirPrint0()" << endl;
    }
    virtual void FirPrint1(void) {
        cout << "TestVirPtr0->FirPrint1()" << endl;
    }
};

class TestVirPtr1
{
    virtual void SecPrint0(void) {
        cout << "TestVirPtr1->SecPrint0()" << endl;
    }
    virtual void SecPrint1(void) {
        cout << "TestVirPtr1->SecPrint1()" << endl;
    }
};

class TestVirPtr: public TestVirPtr0, public TestVirPtr1
{
    virtual void Print0(void) {
        cout << "TestVirPtr->Print0()" << endl;
    }
    virtual void Print1(void) {
        cout << "TestVirPtr->Print1()" << endl;
    }
};

typedef void (*print)(void);

int main(void)
{
    TestVirPtr test;

    /*
        虚表以及虚函数在类中存储类似这样的结构
        test {
            void **vtable0[];
            void **vtable1[];
                    .
                    .
                    .
            void **vtablen[];
        }
    */

    //*(long*)test 得到第一个虚表地址,虚表存放虚函数的指针地址
    long *vtable0 = (long*) (*((long*)&test+0));
    //*vtable得到虚表第一个元素,即第一个虚函数
    print p = (print)(*vtable0);
    p();    //输出 TestVirPtr0->FirPrint0()
    //虚表地址+1,得到虚表第二个元素,即第二个虚函数
    print p1 = (print)(*(vtable0+1));
    p1();    //输出 TestVirPtr0->FirPrint1()

    //*(long*)test 得到第二个虚表地址,虚表存放虚函数的指针地址
    long *vtable1 = (long*) (*((long*)&test+1));
    //*vtable得到虚表第一个元素,即第一个虚函数
    p = (print)(*vtable1);
    p();    //输出 TestVirPtr1->SecPrint0()
    //虚表地址+1,得到虚表第二个元素,即第二个虚函数
    p1 = (print)(*(vtable1+1));
    p1();    //输出 TestVirPtr1->SecPrint1()

    /** 执行会崩溃,因为已经越界了 */
    // //*(long*)test 得到第三个虚表地址,虚表存放虚函数的指针地址
    // long *vtable2 = (long*) (*((long*)&test+2));
    // //*vtable得到虚表第一个元素,即第一个虚函数
    // p = (print)(*vtable2);
    // p();
    // //虚表地址+1,得到虚表第二个元素,即第二个虚函数
    // p1 = (print)(*(vtable2+1));
    // p1();

    /**
     *  父类存在虚函数的情况下,子类的虚函数不会另外增加一个虚表去管理,默认附加在第一个继承父类的虚函数后面
     */
    print p2 = (print)(*(vtable0+2)); p2();    //输出 TestVirPtr->Print0()

    return 0;
}

输出结果:

由此代码小实验可知C++的虚表和虚函数是如何存储的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值