c++中的物件模型

PRO_Z發表於2021-07-20

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 繼承中的物件模型

  子類是由父類成員疊加子類中的新成員形成的。

     

相關文章