【C++】2、虚函数表和虚继承

本文通过具体的C++代码示例,详细介绍了虚函数表的工作原理及虚继承的实现方式。通过对比非虚继承与虚继承下对象布局的不同,阐述了虚继承如何解决二义性问题,并分析了虚函数表指针对类实例大小的影响。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

2、虚函数表和虚继承

2.1、虚函数表

class CBase
{
    public:
        CBase() : m_s64Value(0){printf("[%s:%d]:%p, () CBase\n", __func__, __LINE__, this);}
        virtual void FunTest0(){printf("[%s:%d]:%p, () CBase\n", __func__, __LINE__, this);}
        virtual void FunTest1(){printf("[%s:%d]:%p, CBase\n", __func__, __LINE__, this);}
        virtual void FunTest2(){printf("[%s:%d]:%p, CBase\n", __func__, __LINE__, this);}
        virtual void FunTest3(){printf("[%s:%d]:%p, CBase\n", __func__, __LINE__, this);}
        ~CBase() {printf("[%s:%d]:%p, CBase destory\n",      __func__, __LINE__, this);}
        long m_s64Value;
};

class Base1 : public CBase
{
public:
    Base1(): m_s64Value(1) {printf("[%s:%d]:%p, Base1\n", __func__, __LINE__, this);}
    virtual void FunTest1(){printf("[%s:%d]:%p, Base1\n", __func__, __LINE__, this);}
    virtual void FunTest7(){printf("[%s:%d]:%p, Base1\n", __func__, __LINE__, this);}
    ~Base1() {printf("[%s:%d]:%p, Base1 destory\n",      __func__, __LINE__, this);}
    long m_s64Value;
};

class Base2 : public CBase
{
public:
    Base2() : m_s64Value(2){}
    virtual void FunTest2(){printf("[%s:%d]:%p, Base2\n", __func__, __LINE__, this);}
    virtual void FunTest8(){printf("[%s:%d]:%p, Base2\n", __func__, __LINE__, this);}
    long m_s64Value;
};

class Base3 : public Base1, Base2
{
public:
    Base3(): m_s64Value(3){}
    void FunTest3(){printf("[%s:%d]:%p, Base3\n", __func__, __LINE__, this);}
    void FunTest7(){printf("[%s:%d]:%p, Base3\n", __func__, __LINE__, this);}
    void FunTest8(){printf("[%s:%d]:%p, Base3\n", __func__, __LINE__, this);}
    void FunTest9(){printf("[%s:%d]:%p, Base3\n", __func__, __LINE__, this);}
    long m_s64Value;
};

typedef void(*FUNC)(void);
void PrintVTable(intptr_t* VTable)
{
    cout << " 虚表地址" << VTable << endl;
    for (long i = 0; VTable[i] > 0xfff; ++i)
    {
        printf(" 第%ld个虚函数地址 :%#lx, ->", i, VTable[i]);
        FUNC f = (FUNC)VTable[i];
        f();
    }
    cout << endl;
}
void main()
{
	Base3 dafgsgh;
	printf("[%s:%d] size:%ld \n", __func__, __LINE__, sizeof(Base3));
	for (int i=0; i<sizeof(Base3) / sizeof(char *); i++) {
	    printf("[%s:%d] addr:%p, value:%#lx \n", __func__, __LINE__, (intptr_t *)&dafgsgh+1, *((intptr_t *)&dafgsgh + i));
	}
	for (int i=0; i<sizeof(Base3) / sizeof(char *); i++) {
	    if (*((intptr_t *)&dafgsgh + i) > 10) {
	      PrintVTable((intptr_t *)*((intptr_t *)&dafgsgh + i));
	    }
	}
}

在这里插入图片描述

小编的平台是64位的PC机跑Ubuntu。
2个CBase对象+1个Base1+1个Base2+1个Base3,2张虚函数表指针变量
每个对象有一个long成员变量,所以总共有5个对象,2张虚表指针,实例size: 7 * 8 = 56字节;

2.2、虚继承

将上面新增virtual

class Base1 : public CBase
class Base2 : public CBase

修改为

class Base1 : virtual public CBase
class Base2 : virtual public CBase

在这里插入图片描述

小编的平台是64位的PC机跑Ubuntu。
这里变化的是:只有1个CBase对象,多了一张虚表指针变量。
1个CBase对象+1个Base1+1个Base2+1个Base3,3张虚函数表指针变量
每个对象有一个long成员变量,所以总共有4个对象,3张虚表指针,实例size: 7 * 8 = 56字节;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值