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 }
补充:字节对齐知识点
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 继承中的对象模型
子类是由父类成员叠加子类中的新成员形成的。