C++类继承的内存布局

一 代码

#include "stdafx.h"
#include <iostream>
using namespace std;

typedef void (*pFunc)();

class MyBase{
public:
    virtual void vfunA() {
        std::cout << "call MyBase::vfunA" << std::endl;
    }

    virtual void vfunB() {
        std::cout << "call MyBase::vfunB" << std::endl;
    }

    void funC() {
        std::cout << "call MyBase::funC" << std::endl;
    }

    void funD() {
        std::cout << "call MyBase::funD" << std::endl;
    }
public:
    int m_a;
    int m_b;
};

class MyDerived : public MyBase{
public:
    virtual void vfunA() {
        std::cout << "call MyDerived::vfunA" << std::endl;
    }
    /*
    virtual void vfunB() {
        std::cout << "call MyDerived::vfunB" << std::endl;
    }
    */

    void funD1() {
        std::cout << "call MyDerived::funD1" << std::endl;
    }
public:
    int m_c;
    int m_d;
};

int main() {
    std::cout << "hello,world!" << std::endl;

    std::cout << "打印基类的内存结构" << std::endl;
    MyBase baseObj;
    std::cout << "1: 占用内存" << std::endl;
    std::cout << "sizeof(baseObj) = "<< sizeof(baseObj) << std::endl;
    
    std::cout << "2: 对象首地址" << std::endl;
    std::cout << "&baseObj = " << &baseObj << std::endl;

    std::cout << "3: 对象虚函数地址" << std::endl;
    //首先获取obj的地址,也即内存首地址,首地址中存放的是指针(vptr),所以p 实际上就是指针的指针
    void **p = (void **)&baseObj;
    //*p取得的是vptr的值,vptr指向虚函数表,虚函数表中存放的是指针(函数指针),所以vptr实际上也是指针的指针
    void **vptr = (void **)*p;		//相当于 void *vptr[]; 表明是一个数组,数组中存放的是指针
    printf("obj MyDerived::vfunA: %p\n", vptr[0]);    //第一个虚函数的函数指针
    pFunc vfunAObj = (pFunc)*((int*)(vptr+0));
    vfunAObj();

    printf("obj MyDerived::vfunB: %p\n", vptr[1]);    //第二个虚函数的函数指针
    pFunc vfunBObj = (pFunc)*((int*)(vptr+1));
    vfunBObj();

    cout << "4: 对象成员函数地址" << endl;
    printf("MyBase::funC() \t addr: 0x%p\n", &MyBase::funC);
    printf("MyBase::funD() \t addr: 0x%p\n", &MyBase::funD);

    cout << "5: 对象成员变量地址" << endl;
    printf("&baseObj.m_a \t addr: 0x%p\n", &baseObj.m_a);
    printf("&baseObj.m_b \t addr: 0x%p\n", &baseObj.m_b);

    std::cout << "打印派生类的内存结构" << std::endl;
    MyDerived derivedObj;
    std::cout << "1: 占用内存" << std::endl;
    std::cout << "sizeof(derivedObj) = "<< sizeof(derivedObj) << std::endl;
    
    std::cout << "2: 对象首地址" << std::endl;
    std::cout << "&derivedObj = " << &derivedObj << std::endl;

    std::cout << "3: 对象虚函数地址" << std::endl;
    //首先获取obj的地址,也即内存首地址,首地址中存放的是指针(vptr),所以p 实际上就是指针的指针
    void **p1 = (void **)&derivedObj;
    //*p取得的是vptr的值,vptr指向虚函数表,虚函数表中存放的是指针(函数指针),所以vptr实际上也是指针的指针
    void **vptr1 = (void **)*p1;		//相当于 void *vptr[]; 表明是一个数组,数组中存放的是指针
    printf("obj MyDerived::vfunA: %p\n", vptr1[0]);    //第一个虚函数的函数指针
    printf("obj MyDerived::vfunB: %p\n", vptr1[1]);    //第二个虚函数的函数指针



    cout << "4: 对象成员函数地址" << endl;
    printf("MyDerived::funC() \t addr: 0x%p\n", &MyDerived::funC);
    printf("MyDerived::funD() \t addr: 0x%p\n", &MyDerived::funD);
    printf("MyDerived::funD1() \t addr: 0x%p\n", &MyDerived::funD1);

    cout << "5: 对象成员变量地址" << endl;
    printf("&derivedObj.m_a \t addr: 0x%p\n", &derivedObj.m_a);
    printf("&derivedObj.m_b \t addr: 0x%p\n", &derivedObj.m_b);
    printf("&derivedObj.m_c \t addr: 0x%p\n", &derivedObj.m_c);
    printf("&derivedObj.m_d \t addr: 0x%p\n", &derivedObj.m_d);

    return 0;
}
hello,world!
打印基类的内存结构
1: 占用内存
sizeof(baseObj) = 12
2: 对象首地址
&baseObj = 0054FB0C
3: 对象虚函数地址
obj MyDerived::vfunA: 00591032
call MyBase::vfunA
obj MyDerived::vfunB: 00591181
call MyBase::vfunB
4: 对象成员函数地址
MyBase::funC()   addr: 0x00591014
MyBase::funD()   addr: 0x0059100A
5: 对象成员变量地址
&baseObj.m_a     addr: 0x0054FB10
&baseObj.m_b     addr: 0x0054FB14
打印派生类的内存结构
1: 占用内存
sizeof(derivedObj) = 20
2: 对象首地址
&derivedObj = 0054FAC0
3: 对象虚函数地址
obj MyDerived::vfunA: 0059108C
obj MyDerived::vfunB: 00591181
4: 对象成员函数地址
MyDerived::funC()        addr: 0x00591014
MyDerived::funD()        addr: 0x0059100A
MyDerived::funD1()       addr: 0x0059109B
5: 对象成员变量地址
&derivedObj.m_a          addr: 0x0054FAC4
&derivedObj.m_b          addr: 0x0054FAC8
&derivedObj.m_c          addr: 0x0054FACC
&derivedObj.m_d          addr: 0x0054FAD0
请按任意键继续. . .

二 类继承的内存结构

网上找的相似的类图,后续有时间再补上新图,和详细讲解。
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值