您的位置:首页 > 编程语言 > C语言/C++

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

2018-01-21 14:31 363 查看

1、回归本质

    1.1、class是一种特殊的结构体
        1.1.1、在内存中class依旧可以看作变量的集合
        1.1.2、class与struct遵循相同的内存对齐规则
        1.1.3、class中的成员函数与成员变量是分开存放的。即每个对象有独立的成员变量,但所有对象共享类中的成员函数

/******************* 对象内存布局初探 ******************/
#include <iostream>
#include <string>
using namespace std;
#pragma pack(4)
class A
{
    //默认访问权限private
    int i;
    int j;
    char c;
    double d;

public:
    void print()
    {
        cout << "i = " << i << ", "
             << "j = " << j << ", "
             << "c = " << c << ", "
             << "d = " << d << endl;
    }
};
#pragma pack(4)             //在结构体面前指定对齐字节数。
struct B
{
    //默认访问权限public
    int i;
    int j;
    char c;
    double d;
};
/*
  对于对齐原则的总结:首先先想是不是32位系统,或者64位系统, 如果想要调整内存对齐,用语句
*/
A a;
int main()
{
    A a;

    //class和struct在内存布局上是一样的,大小相同。
    cout << "sizeof(A)" << sizeof(A) << endl;
    cout << "sizeof(a)" << sizeof(a) << endl;   //g++下输出20byte
    cout << "sizeof(B)" << sizeof(B) << endl;

    cout << endl;

    a.print();      //对象未初始化,在栈上创建,值是随机的
    //二者内存地址相同。

    B* p = reinterpret_cast<B*>(&a);//将A这个类对象指针强制转化为结构体指针,(用在指针和指针类型之间的转换或者整数和指针期间。)

    //利用结构体指针对类的private成员进行赋值(注意是private成员),说明class在运行时,private访问权限只在编译期起作用。
    p->i = 100;
    p->j = 200;
    p->c = 'C';
    p->d = 3.14;

    a.print();  //class中的private成员被改变。

    cout << endl;

    return 0;
}

    1.2、运行时的对象退化为结构体的形式
        1.2.1、所有成员变量在内存中依次排布
        1.2.2、成员变量间可能存在内存空隙
        1.2.3、可以通过内存地址直接访问成员变量
        1.2.4、访问权限关键字在运行时失效

2、C++对象模型

    2.1、类中的成员函数位于代码段
    2.2.、调用成员函数时对象地址作为参数隐式传递(this关键字,对象的地址)
    2.3、成员函数通过对象地址访问成员变量
    2.4、C++语法规则隐藏了对象地址的传递过程

对象本质分析(用C写面向对象)

/******************************    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语言实现面向对象

#ifndef _50_2_H_
#define _50_2_H_
//为什么是void,直接指针类型(结构体指针类型)不行吗?
typedef void Demo;  //进行了隐藏,和private的联系 仔细体会,模拟private,防止外界通过指针访问结构体里面的变量。 分离
//声明成员函数(接口),,每当调用这些成员函数时候,总有对象地址传递过程
Demo* Demo_Create(int i, int j);//类似构造函数
int Demo_GetI(Demo* pThis);
int Demo_GetJ(Demo* pThis);  //Demo 是typedef void Demo类型
int Demo_Add(Demo* pThis, int value);
void Demo_Free(Demo* pThis);
#endif

#include "50-2.h"
#include <malloc.h>
#include <stdio.h>
//利用C语言来实现面向对象
//定义结构体
struct ClassDemo
{
    int mi
;

    int mj;
};
//实现各成员函数(带this指针)
//构造函数   申请空间,初始化空间
Demo* Demo_Create(int i, int j)
{
    struct ClassDemo* ret = (struct ClassDemo*)malloc(sizeof(struct ClassDemo));
    
    if(ret != NULL)
    {
        ret -> mi = i;
        ret -> mj = j;
    }
    else
    {
        printf("ERROR\n");
    }
    
    return ret;             //将Demo改变为结构体类型,看看能否访问
}

int Demo_GetI(Demo* pThis)
{
    struct ClassDemo* obj = (struct ClassDemo*)pThis;
    
    return obj->mi;
}

int Demo_GetJ(Demo* pThis)
{
    struct ClassDemo* obj = (struct ClassDemo*)pThis;
    
    return obj->mj;
}

int Demo_Add(Demo* pThis, int value)
{
    struct ClassDemo* obj = (struct ClassDemo*)pThis;
    
    return obj->mi + obj->mj + value;
}

//析构函数
void Demo_Free(Demo* pThis)
{
    free(pThis);
}

#include <stdio.h>
#include "50-2.h"
int main()
{
    //Demo是void类型的,typedef void Demo;
    Demo* d = Demo_Create(1, 2); // 构造函数, Demo* d = new Demo(1, 2);
    
    //各函数调用中,传入this指针:d  。C++中
    printf("d.mi = %d\n", Demo_GetI(d));      //d->getI(); //d具体的类指针
    printf("d.mj = %d\n", Demo_GetJ(d));      //d->getJ()
    printf("Add(3) = %d\n", Demo_Add(d, 3));    //d->Add(3)
    
    //d->mi = 100;    //这个d只是void类型,mi相当于私有变量,不能直接通过this指针d来访问。
    
    Demo_Free(d);
    
    return 0;
}

3、
小结

    3.1、C++中的类对象在内存布局上与结构体相同
    3.2、成员变量和成员函数在内存中分开存放
    3.3、访问权限关键字在运行时失效
    3.4、调用成员函数时对象地址作为参数隐式传递

总结:注意因为要模拟数据私有性private,所以函数的参数应该用void,在函数内再具体操作数据。防止外界直接访问。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: