c++中的对象模型

1 对象模型的前世

  类在c++编译器内部可以理解成结构体,所以在对象模型分析时,我们可以把 class  当作一种特殊的 struct

  1)在内存中 class 可以看作是普通成员变量的集合;

  2)class 与 struct 遵循相同的内存对齐规则;

  3)class 中的 成员变量 与 成员函数 是分开存放的;

    1. 每个对象都有独立的成员变量;成员变量可以存储在 栈空间、堆空间、全局数据区;

    2. 所有对象共享类的成员函数;成员函数 只能存储在 代码段;

      理解下面这 3 句话:(对象地址 == this指针)

        1、成员函数通过对象地址访问成员变量;

        2、调用成员函数时将对象地址作为参数隐式传递

        3、c++语法规则隐藏了对象地址的传递过程;

  4)访问权限关键字在运行时失效;(外界访问类的私有成员时只在编译阶段有效)

  注:若没有明确说是 static 成员时,默认都是 普通成员;    

  代码分析:

 1 #include <iostream>
 2 #include <string>
 3 
 4 using namespace std;
 5 
 6 #pragma pack(push, 4) // 将数据存储方式设置为 压栈方式,字节对齐方式 设置为 4
 7 
 8 class A
 9 {
10     static int count;    // 静态成员变量在类的外部单独分配空间,静态成员变量在程序内部位于 全局数据区
11     char *pt;    // 8 bytes(OS:64bit)
12     char c;     // 1 bytes
13     int i;      // 4 bytes
14     double d;   // 8 bytes
15 public:
16     A(const char *pt = NULL, char c = ' ', int i = 0, double d = 0)
17     {
18         this->pt = new char(' ');
19         this->c = ' ';
20         this->i = i;
21         this->d = 0;
22     }
23     void print()
24     {
25         cout << "*pt = " << *pt << ", "
26              << "c = " << c << ", "
27              << "i = " << i << ", "
28              << "d = " << d << endl;
29     }
30     ~A()
31     {
32         delete pt;
33     }
34 };
35 
36 int A:: count = 0;
37 
38 struct B
39 {
40     char *pt;    // 8 bytes(OS:64bit)
41     char c;     // 1 bytes
42     int i;      // 4 bytes
43     double d;   // 8 bytes
44 };
45 
46 #pragma pack(pop)// 恢复压栈前的设置
47 
48 int main()
49 {
50     A a;
51     
52     cout << "sizeof(a) = " << sizeof(a) << endl;    // 24 bytes
53     cout << "sizeof(A) = " << sizeof(A) << endl;    // 24 bytes
54     cout << "sizeof(B) = " << sizeof(B) << endl;    // 24 bytes
55     
56     a.print();  // *pt =  , i = 0, c =  , d = 0
57     
58     B* p = reinterpret_cast<B*>(&a);    // struct 与 class 的内存模型相同  
59     
60     *(p->pt) = 'P';
61     p->c = 'C';
62     p->i = 100;
63     p->d = 3.14;
64     
65     a.print();  // *pt = P, i = 100, c = C, d = 3.14
66     
67     return 0;
68 }
单个类对象的内存模型练习
 1 // demo.h
 2 
 3 #ifndef _DEMO_H_
 4 #define  _DEMO_H_
 5 
 6 typedef void Demo;
 7 
 8 Demo* demo_Create(int i, int j);        // 等价于 c++ 构造函数 Demo(int i, int j)
 9 int demo_getI(Demo *pThis);             // 等价于 c++ 成员函数 int getI()
10 int demo_getJ(Demo *pThis);             // 等价于 c++ 成员函数 int getJ()
11 int demo_add(Demo *pThis, int value);   // 等价于 c++ 成员函数 int add(int value)  
12 Demo demo_free(Demo *pThis);            // 等价于 c++ 析构函数 ~Demo()           
13 
14 #endif
15 
16 // demo.c
17 #include "demo.h"
18 #include "malloc.h"
19 
20 typedef struct DemoStruct
21 {
22     int i;
23     int j;
24 } DemoStruct;
25 
26 Demo* demo_Create(int i, int j)
27 {
28     DemoStruct *this = (DemoStruct*)malloc( sizeof(DemoStruct) );
29 
30     if(this != NULL)
31     {
32         this->i = i;
33         this->j = j;
34     }
35 
36     return this;
37 }
38 
39 int demo_getI(Demo *pThis)
40 {
41     DemoStruct *this = (DemoStruct*)pThis;
42 
43     return this->i;
44 }
45 
46 int demo_getJ(Demo *pThis)
47 {
48     DemoStruct *this = (DemoStruct*)pThis;
49 
50     return this->j;
51 }
52 
53 int demo_add(Demo *pThis, int value)
54 {
55     DemoStruct *this = (DemoStruct*)pThis;
56 
57     return (this->i +  this->j + value);
58 }
59 
60 Demo demo_free(Demo *pThis)
61 {
62     DemoStruct *this = (DemoStruct*)pThis;
63 
64     free(this);
65 }
66 
67 // mian.c
68 
69 #include "stdio.h"
70 #include "demo.h"
71 
72 int main(int argc, char const *argv[])
73 {
74     Demo *d = demo_Create(10, 20);    //  相当于 c++中的 Demo* d = new Demo(10, 20);
75 
76     int i = demo_getI(d);   //  相当于 c++中的 d->getI();
77     int j = demo_getJ(d);   //  相当于 c++中的 d->getJ();
78     int v = demo_add(d, 30); //  相当于 c++中的 d->add(30);
79 
80     printf("i = %d, j = %d, v = %d\n", i, j, v);    // i = 10, j = 20, v = 60
81 
82     // d->i = 11;  // err, 相当于 c++的private属性
83 
84     demo_free(d);
85 
86     return 0;
87 }
用c语言复现c++中的this指针 

补充:字节对齐知识点

 1 /*
 2       #pragma pack(push, 4)  《=》
 3       #pragma pack(push)
 4       #pragma pack(4)
 5 */
 6 #pragma pack(push, 4) // 将数据存储方式设置为 压栈方式,字节对齐方式 设置为 4
 7 struct S
 8 {
 9     char c;
10     int i;
11 };
12 #pragma pack(pop)    // 恢复压栈前的设置
13 
14 #pragma pack (4)      //作用:C编译器将按照4个字节对齐。
15 struct S
16 {
17     char c;
18     int i;
19 }
20 #pragma pack ()       // 作用:取消自定义字节对齐方式
c/c++字节对齐方式设置

2 继承中的对象模型

  子类是由父类成员叠加子类中的新成员形成的。

     

posted @ 2021-07-20 16:52  PRO_Z  阅读(92)  评论(0编辑  收藏  举报