C++对象模型分析(上)

  • 回归class(对象)的本质
  1. class是一种特殊的struct
  2. 在内存中class依旧可以看作变量的集合
  3. class与struct遵循相同的内存对齐规则
  4. class中的成员函数与成员变量是分开存放的,每个对象有独立的成员变量,所有对象共享类中的成员函,。
  • 思考一个问题
C++对象模型分析(上)
  • 对象内存布局实验
 1 // 对象内存布局实验.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
 2 //
 3 #include <iostream>
 4 #include <string>
 5 using namespace std;
 6 class A
 7 {
 8         int a;
 9         int b;
10         char c;
11         double d;
12 public:
13         void print()
14         {
15                cout << "a=" << a << ","
16                         << "b=" << b << ","
17                         << "c=" << c << ","
18                         << "d=" << d << endl;
19         }
20         
21 };
22 struct B
23 {
24         int a;
25         int b;
26         char c;
27         double d;
28 };
29 int main()
30 {
31         A a;
32         a.print();
33         cout << "sizeof(A) = " << sizeof(A) << endl;
34         cout << "sizeof(a) = " << sizeof(a) << endl;
35         cout << "sizeof(B) = " << sizeof(B) << endl;
36         B* p = reinterpret_cast<B*>(&a);
37         p->a = 1;
38         p->b = 2;
39         p->c = 'C';
40         p->d = 1.234;
41         a.print();
42 }
  • 运行结果
a=-858993460,b=-858993460,c=?d=-9.25596e+61
sizeof(A) = 24
sizeof(a) = 24
sizeof(B) = 24
a=1,b=2,c=C,d=1.234
  • 运行时的对象退化为结构体的形式
  1. 所有成员变量在内存中依次排布
  2. 成员变量可能存在内存空隙
  3. 可以通过内存地址直接访问成员变量
  4. 访问权限关键字在运行时失效
  5. 类中的成员函数位于代码段中
  6. 调用成员函数时对象地址作为参数隐式传递
  7. 成员函数通过对象地址访问成员变量
  8. C++语法规则隐藏了对象地址的传递过程
  • 实验:用C语言来写面向对象,加深C++面向对象的理解。
main.c
 1 #include "stdio.h"
 2 #include "oop.h"
 3 int main()
 4 {
 5         struct OOP* THIS = NULL;
 6         //【step1】执行“构造函数”
 7         THIS = (struct OOP*)Great_Object(1,2);
 8         //【step2】执行成员函数,成员函数必须带有对象地址,通过对象地址访问成员变量
 9         printf("THIS->value1=%d\n", GET_Value1(THIS));
10         printf("THIS->value2=%d\n", GET_Value2(THIS));
11         //【step3】执行“析构函数”
12         Free_Object(THIS);
13 }
14 
  OOP.c
 1 #include "oop.h"
 2 #include "stdio.h"
 3 DEMO* Great_Object(int i, int j)
 4 {
 5         struct OOP* Object = (struct OOP*)malloc(sizeof(struct OOP));
 6         if (Object!=NULL)
 7         {       
 8                Object->value1 = 1;
 9                Object->value2 = 2;
10         }
11         return Object;
12 }
13 int GET_Value1(DEMO* pthis)
14 {
15         struct OOP* ret = (struct OOP*)pthis;
16         return ret->value1;
17 }
18 int GET_Value2(DEMO* pthis)
19 {
20         struct OOP* ret = (struct OOP*)pthis;
21         return ret->value2;
22 }
23 void Free_Object(DEMO* pthis)
24 {
25         free(pthis);
26 }
OOP.h
#ifndef _OOP_H_
#define _OOP_H_
typedef void DEMO;
struct OOP
{
        int value1;
        int value2;
};
//【step1】模拟C++的构造函数,需要返回this指针
DEMO* Great_Object(int i,int j);
//【step2】定义成员函数,获取成员变量的值,需要传递对象的地址
int GET_Value1(DEMO* pthis);
//【step2】定义成员函数,获取成员变量的值,需要传递对象的地址
int GET_Value2(DEMO* pthis);
//......
//【step3】模拟C++中的析构函数
void Free_Object(DEMO* pthis);
#endif
  • 小结
  1. C++中的类对象在内存布局上与结构体相似
  2. 成员变量和成员函数在内存中分开存放
  3. 访问权限关键字在运行时失效
  4. 调用成员函数时对象地址作为参数隐式传递
 
上一篇:JavaScript面向对象(一)——JS OOP基础与JS 中This指向详解


下一篇:Java语言特性