打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
多重继承的内存布局、数据成员指针偏移量及空指针
 C++ Code 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
struct Base1 {int val10;int val11;};
struct Base2 {int val20;};
struct Derived : public Base2, Base1 {int val;};

// 多重继承下,数据的布局
/*
 *  @Func : 在VC环境下,测试多重继承的内存布局,及数据成员指针
             Address 0: 20
             Address 4: 10
             Address 8: 11
             Address 12: 3

             &Base1::val10 = 00000000
             &Base1::val11 = 00000004
             &Base2::val20 = 00000000
             &Derived::val10 = 00000000
             &Derived::val20 = 00000000
             &Derived::val11 = 00000004
             &Derived::val = 0000000C

             空数据成员指针 地址 = 0019F65C,值 = FFFFFFF
             &Base1::val10 地址 = 0019F650,值 = 00000000
             &Base1::val11 地址 = 0019F644,值 = 00000004
             &Base2::val20 地址 = 0019F638,值 = 00000000
             &Derived::val10 地址 = 0019F62C,值 = 000000
             &Derived::val11 地址 = 0019F620,值 = 000000
             &Derived::val20 地址 = 0019F614,值 = 000000
             &Derived::val 地址 = 0019F608,值 = 0000000C
 * (1)从地址的值来看,内存布局为Base2→Base1→Derived;(2) 基类变量的数据成员指针具有相同的偏移,为0。与书中描述不符
 * (3) 空数据成员指针的值为FFFFFFFF,而数据成员函数的指针则是偏移量。由于对空数据成员指针的特殊赋值,使得偏移量不需要+1
 *
 * @说明:(1)对于多重继承的内存布局,VC的结果与书中的相同;(2)对于数据成员指针的偏移,VC的结果与书中出入很大
 */

void Test_DataMember_Pointer(){
    Derived d; d.val = 3;
    d.val10 = 10; d.val11 = 11;
    d.val20 = 20;

    // 通过观察值得到内存布局
    printf("Address 0: %d \n", *((int*)(int(&d)))); // 从测试结果来看,首地址为Base2::val20
    printf("Address 4: %d \n", *((int*)(int(&d)+4))); // 从测试结果来看,该地址为Base1::val10
    printf("Address 8: %d \n", *((int*)(int(&d)+8))); // 从测试结果来看,该地址为Base1::val11
    printf("Address 12: %d \n\n", *((int*)(int(&d)+12))); //从测试结果来看,该地址为Derived::val

    // 数据成员指针偏移量
    printf("&Base1::val10 = %p \n", &Base1::val10);
    printf("&Base1::val11 = %p \n", &Base1::val11);
    printf("&Base2::val20 = %p \n", &Base2::val20);
    printf("&Derived::val10 = %p \n", &Derived::val10); // 从测试结果来看,&Derived::val10、&Derived::val11与&Derived::val20的偏移相同,均为0
    printf("&Derived::val20 = %p \n", &Derived::val20);
    printf("&Derived::val11 = %p \n", &Derived::val11); 
    printf("&Derived::val = %p \n\n", &Derived::val); // 偏移12

    // 空数据成员指针与数据成员指针的比较
    int CPoint::*p00 = 0;
    int Base1::*p10 = &Base1::val10;
    int Base1::*p11 = &Base1::val11;
    int Base2::*p20 = &Base2::val20;
    int Derived::*p30 = &Derived::val10;
    int Derived::*p31 = &Derived::val11;
    int Derived::*p32 = &Derived::val20;
    int Derived::*p33 = &Derived::val;

    printf("空数据成员指针 地址 = %p,值 = %p \n", &p00, p00);
    printf("&Base1::val10 地址 = %p,值 = %p \n", &p10, p10);
    printf("&Base1::val11 地址 = %p,值 = %p \n", &p11, p11);
    printf("&Base2::val20 地址 = %p,值 = %p \n", &p20, p20);
    printf("&Derived::val10 地址 = %p,值 = %p \n", &p30, p30);
    printf("&Derived::val11 地址 = %p,值 = %p \n", &p31, p31);
    printf("&Derived::val20 地址 = %p,值 = %p \n", &p32, p32);
    printf("&Derived::val 地址 = %p,值 = %p \n", &p33, p33);
}
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
多态性
请求页式存储管理的页面置换算法
指针的基本地址操作(yc)
初探二维指针
动态内存分配,地址对齐
关于指针变量在内存中所在的长度(转载)
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服