zoukankan      html  css  js  c++  java
  • 第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语言写面向对象。

    小结:

  • 相关阅读:
    【leetcode】704.BinarySearch
    【leetcode】75.Sort Colors
    MongoChef
    问题 工具的缺陷
    MongoDB
    SpringFox
    npm 包管理工具
    RESTful 设计工具和Web框架
    笔记_JSON
    jsoup: Java HTML Parser
  • 原文地址:https://www.cnblogs.com/wanmeishenghuo/p/9575779.html
Copyright © 2011-2022 走看看