C++ 对象模型 -- vptr 和 vtbl

        是看侯捷老师讲解c++对象模型 虚表和虚指针的笔记和程序验证。

        先看两张关键的图吧,右边的三个基类和派生类 A,B,C。定义了两个虚函数,两个一般成员函数,以及几个成员变量。

        

        只有在类中有虚函数时,才会有虚指针以及虚表。一般函数和变量是通过静态绑定方式,调用时通过call xxx(函数地址)访问;而虚函数则是通过 对象指针 -> 虚指针- >虚表 -> 对应函数 这个过程来访问,这也是动态绑定方式。

#include <iostream>
#include <type_traits>

class Base {
public:
    Base() {
        std::cout << "Base \n";
    }
    ~Base() {
        std::cout << "~Base \n";
    }

    virtual void vfunc1() {
        std::cout << "vfunc1 \n";
    }

    virtual void vfunc2() {
        std::cout << "vfunc2 \n";
    }

    void func1() { std::cout << "func1 \n"; }
    void func2() { std::cout << "func2 \n"; }

    int m_data = 1;

private:
    int m_data1;
    int m_data2;
};

class Sub : public Base {
public:
    Sub() {
        std::cout << "Sub \n";
    }
    ~Sub() {
        std::cout << "~Sub \n";
    }

    virtual void vfunc1() {
        std::cout << "sub vfunc1 \n";
    }

    void func2() { std::cout << "sub func2 \n"; }
};

class SubSub : public Sub {
public:
    SubSub() {
        std::cout << "SubSub \n";
    }
    ~SubSub() {
        std::cout << "~SubSub \n";
    }

    virtual void vfunc1() {
        std::cout << " SubSub vfunc1 \n";
    }

    void func2() { std::cout << "SubSub func2 \n"; }

    int m_data = 2;

private:
    int m_data1;
};

int main() {
    std::cout << "Hello World!\n";

    Base* cls = new SubSub();
    cls->vfunc1();
    cls->func2(); // 静态绑定,会调用这个类型的值。

    auto cls1 = new SubSub();
    cls1->func2();

    std::cout <<( typeid(cls1) == typeid(SubSub) )<<std::endl;
    std::cout << "m_data : " << cls->m_data << std::endl;
    auto obj = dynamic_cast<SubSub*>(cls);
    if (obj) std::cout << "m_data : " << obj->m_data << std::endl;
    

    SubSub s;
    Base& cls2 = s;
    cls2.vfunc1();
    cls2.func2();
    
    // 下面是假设vptr在对象的开头位置,尝试取出它,并对比。发现下面两个对象的vptr 值是一样的,符合预期。
    printf("cls1 vptr value : %p \n", *(&((int*)cls1)[0]));
    printf("cls2 vptr value : %p \n", *(&((int*)&cls2)[0]));


    return 0;
}

   验证结果:

Hello World!
Base 
Sub 
SubSub 
 SubSub vfunc1 
func2 
Base 
Sub 
SubSub 
SubSub func2 
0
m_data : 1
m_data : 2
Base 
Sub 
SubSub 
 SubSub vfunc1 
func2 
cls1 vptr value : 0xb5d62d18 
cls2 vptr value : 0xb5d62d18 
~SubSub 
~Sub 
~Base 

运行结束。

        如果使用多态方式,一般函数的访问取决于用的是什么类型对象访问,

  • 9
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值