第50课 C++对象模型分析(上)

C++的对象模型就是C++的对象在内存中是如何排布的。

C++的对象就包含了成员变量和成员函数。

回归本质:

class和struct遵循相同的内存对齐规则,因此计算class占用的内存大小和struct一样。

值得思考的问题:

对象内存布局初探:

可以看出打印的都是20。

增加成员函数:

 1 #include <iostream>
 2 #include <string>
 3 
 4 using namespace std;
 5 
 6 class A
 7 {
 8     int i;
 9     int j;
10     char c;
11     double d;
12 public:
13     void print()
14     {
15         cout << "i = " << i << ", "
16              << "j = " << j << ", "
17              << "c = " << c << ", "
18              << "d = " << d << endl;
19     }
20 };
21 
22 struct B
23 {
24     int i;
25     int j;
26     char c;
27     double d;
28 };
29 
30 int main()
31 {
32     A a;
33     
34     cout << "sizeof(A) = " << sizeof(A) << endl;    // 20 bytes
35     cout << "sizeof(a) = " << sizeof(a) << endl;
36     cout << "sizeof(B) = " << sizeof(B) << endl;    // 20 bytes
37     
38     a.print();
39     
40     B* p = reinterpret_cast<B*>(&a);
41     
42     p->i = 1;
43     p->j = 2;
44     p->c = 'c';
45     p->d = 3;
46     
47     a.print();
48     
49     p->i = 100;
50     p->j = 200;
51     p->c = 'C';
52     p->d = 3.14;
53     
54     a.print();
55     
56     return 0;
57 }

 第40行的强制类型转换表示重解释这段内存。

运行结果如下:

 

访问权限关键字只在编译时有效。通过指针可以修改成员变量的值。

 我们调用成员函数时,在背后发生了什么?

 对象的本质分析:

 1 #include <iostream>
 2 #include <string>
 3 
 4 using namespace std;
 5 
 6 class Demo
 7 {
 8     int mi;
 9     int mj;
10 public:
11     Demo(int i, int j)
12     {
13         mi = i;
14         mj = j;
15     }
16     
17     int getI()
18     {
19         return mi;
20     }
21     
22     int getJ()
23     {
24         return mj;
25     }
26     
27     int add(int value)
28     {
29         return mi + mj + value;
30     }
31 };
32 
33 int main()
34 {
35     Demo d(1, 2);
36     
37     cout << "sizeof(d) = " << sizeof(d) << endl;
38     cout << "d.getI() = " << d.getI() << endl;
39     cout << "d.getJ() = " << d.getJ() << endl;
40     cout << "d.add(3) = " << d.add(3) << endl;
41     
42     return 0;
43 }

结果如下:

 this指针是怎么样传递到成员函数中的呢?

我们用C语言来进行深入分析:

 1 #ifndef _50_2_H_
 2 #define _50_2_H_
 3 
 4 typedef void Demo;
 5 
 6 Demo* Demo_Create(int i, int j);
 7 int Demo_GetI(Demo* pThis);
 8 int Demo_GetJ(Demo* pThis);
 9 int Demo_Add(Demo* pThis, int value);
10 void Demo_Free(Demo* pThis);
11 
12 #endif
 1 #include "50-2.h"
 2 #include "malloc.h"
 3 
 4 struct ClassDemo
 5 {
 6     int mi;
 7     int mj;
 8 };
 9 
10 Demo* Demo_Create(int i, int j)
11 {
12     struct ClassDemo* ret = (struct ClassDemo*)malloc(sizeof(struct ClassDemo));
13     
14     if( ret != NULL )
15     {
16         ret->mi = i;
17         ret->mj = j;
18     }
19     
20     return ret;
21 }
22 
23 int Demo_GetI(Demo* pThis)
24 {
25      struct ClassDemo* obj = (struct ClassDemo*)pThis;
26      
27      return obj->mi;
28 }
29 
30 int Demo_GetJ(Demo* pThis)
31 {
32     struct ClassDemo* obj = (struct ClassDemo*)pThis;
33      
34     return obj->mj;
35 }
36 
37 int Demo_Add(Demo* pThis, int value)
38 {
39     struct ClassDemo* obj = (struct ClassDemo*)pThis;
40      
41     return obj->mi + obj->mj + value;
42 }
43 
44 void Demo_Free(Demo* pThis)
45 {
46     free(pThis);
47 }
 1 #include <stdio.h>
 2 #include "50-2.h"
 3 
 4 int main()
 5 {
 6     Demo* d = Demo_Create(1, 2);             // Demo* d = new Demo(1, 2);
 7     
 8     printf("d.mi = %d
", Demo_GetI(d));     // d->getI();
 9     printf("d.mj = %d
", Demo_GetJ(d));     // d->getJ();
10     printf("Add(3) = %d
", Demo_Add(d, 3));    // d->add(3);
11     
12     // d->mi = 100;
13     
14     Demo_Free(d);
15     
16     return 0;
17 }

ClassDemo代表一个类,Demo_Create相当于构造函数。

运行结果如下:

 主函数第12行直接通过d指针修改mi的值,会编译报错:

从面向对象的观点来看,mi是私有的,我们不能从外部访问。

而在C语言中没有private关键字,我们是通过void*指针来实现的。通过void这样的技术来实现信息隐藏。

面向对象不是C++专属的,我们也可以用C语言写面向对象。

小结:

原文地址:https://www.cnblogs.com/wanmeishenghuo/p/9575779.html