zoukankan      html  css  js  c++  java
  • 第五十课、c++对象模型分析(上)

    一、c++对象模型之成员变量

    1、class是一种特殊的struct

    (1)、在内存中class依旧可以看做是变量的集合

    (2)、class与struct遵循相同的内存对齐规则

    (3)、class中的成员函数和成员变量是分开存储

    A、每个对象有独立的成员变量

    B、所有对象共享类中的成员函数

    2、运行时的对象退化为结构体的形式

    (1)、所有成员变量在内存中依次分布

    (2)、成员变量间可能存在内存间隙

    (3)、可以通过内存地址直接访问成员变量

    (4)、访问权限关键字在运行时失效

    #include<iostream>
    
    using namespace std;
    
    class A
    {
    private:
        int i;
        int j;
        char c;
        double d;
    public:
        void print()//保存在代码段中
        {
            cout << "i = " << i << ","
                 << "j = " << j << ","
                 << "c = " << c << ","
                 << "d = " << d << endl;     
        }
    };
    
    struct B
    {
        int i;
        int j;
        char c;
        double d;
    };
    int main()
    {
        A a;
    
        cout << "sizeof(A) = " << sizeof(A) << endl;//4+4+4+8=20
        cout << "sizeof(a) = " << sizeof(a) << endl;//20
        cout << "sizeof(B) = " << sizeof(B) << endl;//20
        a.print();
    
        B *p = reinterpret_cast<B*>(&a);//强制转换成结构体,重新解释这片内存空间
        p->i = 10;
        p->j = 20;
        p->c = 'a';
        p->d = 3.15;//成功改变private的值,说明private只在编译期起作用,运行时失效
        
        a.print();
    
        return 0;
    }
    
    //输出结果
    /*
    sizeof(A) = 20
    sizeof(a) = 20
    sizeof(B) = 20
    i = -1075365380,j = -1219354059,c = p,d = 4.85915e-270
    i = 10,j = 20,c = a,d = 3.15
    */

    二、c++的对象模型之成员函数

    1、类中的成员函数位于代码段中

    2、调用成员函数时对象地址作为参数隐式传递this指针保存了对象的地址,所以即使成员函数和成员变量分开存储,成员函数也可以通过对象的地址访问成员变量

    3、成员函数通过对象地址访问成员变量

    4、c++语法规则隐藏了对象地址的传递过程

    #include <iostream>
    #include <string>
    
    using namespace std;
    
    class Demo
    {
        int mi;
        int mj;
    public:
        Demo(int i, int j)
        {
            mi = i;
            mj = j;
        }
        
        int getI()
        {
            return mi;
        }
        
        int getJ()
        {
            return mj;
        }
        
        int add(int value)
        {
            return mi + mj + value;
        }
    };
    
    int main()
    {
        Demo d(1, 2);
        
        cout << "sizeof(d) = " << sizeof(d) << endl;//8
        cout << "d.getI() = " << d.getI() << endl;//1
        cout << "d.getJ() = " << d.getJ() << endl;//2
        cout << "d.add(3) = " << d.add(3) << endl;//6
        
        return 0;
    }

    用C语言来模拟从而探寻对象的本质:实际上就是函数与变量分开,变量在类中

    //add.h:

    #ifndef _ADD_H_
    #define _ADD_H_
    
    typedef void Demo;
    Demo* Demo_create(int i, int j);//构造函数,返回的返回值是void*的原因是为了数据隐藏,外界无法访问,内部需要访问时再进行强制类型转换回来即可
    int Demo_GetI(Demo* pThis);//C语言不像c++会隐式传递对象指针,所以调用成员函数时要显示传递对象地址
    int Demo_GetJ(Demo* pThis);
    int Demo_add(Demo* pThis, int value);
    void Demo_free(Demo* pThis);//析构函数
    
    #endif

    //add.c

    #include"add.h"
    #include<malloc.h>
    
    struct ClassDemo//定义一个类
    {
        int mi;
        int mj;
    };
    
    Demo* Demo_create(int i, int j)
    {
        struct ClassDemo* ret = malloc(sizeof(struct ClassDemo));
        
        if(ret != NULL)
        {
            ret->mi = i;
            ret->mj = j;
        }
    
        return ret;
    }
    
    int Demo_GetI(Demo* pThis)
    {
        struct ClassDemo* ret = (struct ClassDemo *)(pThis);
        
        return ret->mi;
    }
    
    int Demo_GetJ(Demo* pThis)
    {
        struct ClassDemo* ret = (struct ClassDemo *)(pThis);
    
        return ret->mj;
    }
    
    int Demo_add(Demo* pThis, int value)
    {
        struct ClassDemo* ret = (struct ClassDemo *)(pThis);
    
        return (ret->mi + ret->mj + value);
    }
    
    void Demo_free(Demo* pThis)
    {
        free(pThis);
    }

    //main.c

    #include<stdio.h>
    #include<malloc.h>
    #include"add.h"
    
    int main()
    {
        Demo* d = Demo_create(1, 2);//相当于c++的 Demo* d = new Demo(1, 2)
    
        printf("Demo_GetI(d) = %d
    ", Demo_GetI(d));//1, 相当于d->GetI();
        printf("Demo_GetJ(d) = %d
    ", Demo_GetJ(d));//2
        printf("Demo_add(d,3) = %d
    ", Demo_add(d, 3));//6


      //d->mi = 100;//无法访问, d再这里是void*型的,不是类类型,需要在类实现那里进行强制类型转换,所以这里很好达到了封装的目的 Demo_free(d); return 0; }

    三、小结

    1、c++中的类对象在内存布局上与结构体相同

    2、成员变量和成员函数在内存中分开存放(本质)

    4、访问权限关键字在运行时失效

    3、调用成员函数时对象地址作为参数隐式传递

     

  • 相关阅读:
    tensorflow2.0——简单的三种图像增强方式(翻转,光照,对比度)
    tensorflow2.0——卷积初始化
    tensorflow2.0——实现先卷积后LSTM的网络
    tensorflow2.0——compile-fit实现多输入复合模型
    CMDB-客户端
    saltstack部署
    CMDB实现的四种方式
    理解python中的元类
    RESTful 架构
    Vuex笔记/axios笔记
  • 原文地址:https://www.cnblogs.com/gui-lin/p/6368779.html
Copyright © 2011-2022 走看看