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 }
補充:位元組對齊知識點
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 () // 作用:取消自定義位元組對齊方式
2 繼承中的物件模型
子類是由父類成員疊加子類中的新成員形成的。