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); } |
联系客服