JHHK

欢迎来到我的个人网站
行者常至 为者常成

6、类、对象及对象内存布局

目录

struct和class的用法

一、面向对象的常见知识点

类、对象

成员变量、成员函数

封装、继承、多态

二、struct与class

C++中可以使用struct/class来定义一个类
struct和class的区别
struct的默认成员权限是public
class的默认成员权限是private

struct定义一个类

//类的定义
struct Person{
    //成员变量
    int age;
  
    //成员函数
    void run(void){
        cout<<age<<"run"<<endl;
    }
};

void structUsing(void){
    Person person;//这样就完成了一个对象的创建
    person.age = 18;//访问person对象的成员变量
    person.run();//调用person对象的成员函数
    
    Person * pPerson = &person;//通过指针访问person对象
    pPerson->age = 20;
    pPerson->run();
}

class定义一个类

//类的定义
class Person1{
public://class默认是private,只能内部访问,要想外部访问指定public
    
    //成员变量
    int age;
    
    //成员函数
    void run(void){
        cout<<age<<"run"<<endl;
    }
};

void classUsing(void){
    Person1 person1;//创建一个对象
    person1.age = 18;
    person1.run();
    
    
    Person1 * pPerson1 = &person1;
    pPerson1->age = 20;
    pPerson1->run();
}

上面代码中person对象、pPerson指针的内存都是在函数的栈空间,自动分配和回收的
可以尝试反汇编struct和class,看看是否有其他区别
实际开发中,用class表示类比较多

C++编程规范

每个人都可以有自己的编程规范,没有统一的标准,没有标准答案,没有最好的编程规范

变量名规范参考

全局变量:g_

成员变量:m_

静态变量:s_

常量:c_

使用驼峰标识

对象的内存布局

如果类中有多个成员变量,对象的内存又是如何布局的?

class Student{
public:
    int m_id;
    int m_age;
    int m_height;
    
    void display(){
        cout<<"m_id is "<<m_id<<endl;
        cout<<"m_age is "<<m_age<<endl;
        cout<<"m_height is "<<m_height<<endl;
    }
};


void studentSize(){
    Student stu;
    
    stu.m_id = 123;
    stu.m_age = 18;
    stu.m_height = 180;
    stu.display();
    
    cout<<"sizeof(stu) is "<<sizeof(stu)<<endl;
    cout<<"sizeof(Student) is "<<sizeof(Student)<<endl;
}


void memoryLayoutTest(){
    //创建对象
    Student stu;        //假设stu的地址是    0x0010
    stu.m_id = 10;      //m_id的地址是      0x0010
    stu.m_age = 20;     //m_age的地址是     0x0014
    stu.m_height = 30;  //m_height的地址是  0x0018
    
    //创建指针
    Student * stup = (Student*)&stu.m_age;//stup存储的地址是0x0014
    
    stup->m_id = 40;    //m_id的偏移量是0,将40放入0x0014+0内
    stup->m_age = 50;   //m_age的偏移量是4,将50放入0x0014+4=0x0018内
    
    //打印
    /**
     m_id is 10
     m_age is 40
     m_height is 50
     
     通过对象函数调用会将对象的地址以隐式参数的方式传入函数内部,函数内部通过对象地址+偏移量的方式找到成员变量
     stu的地址值是 0x0010
     m_id is  10          0x0010+0内的值 10
     m_age is 40          0x0010+4内的值 40
     m_height is 50       0x0010+8内的值 50
     */
    stu.display();
    
    
    
    
    //打印
    /**
     m_id is 40
     m_age is 50
     m_height is 32767
     
     通过指针函数调用会将指针变量存储的地址值传入函数内部,
     函数内部通过该地址+偏移量的方式找到成员变量
     stup存储的地址是:0x0014
     m_id is 40         0x0014+0内的值 40
     m_age is 50        0x0010+0内的值 50
     m_height is 32767  0x0010+0内的值 越界 0x7FFF
     
     在windows(x64架构) vs IDE下,函数调用栈开辟空间时内存会被0xcccccccc覆盖,
     目的一是清除之前调用栈的遗留数据
     目的二是0xcccccccc 对应的是一条中断指令 int3 
     防止其它非法内存访问到该内存时能进行中断而不至于产生无法预料的问题。
     
     此处的0x7FFF 猜测也是同样的作用 是一条中断指令
     */
    stup->display();
}

this指针

this是指向当前对象的指针
对象在调用成员函数的时候,会自动传入当前对象的内存地址

可以利用this.m_age来访问成员变量么?
不可以,因为this是指针,必须用this->m_age

class Car{
public:
    int speed;
    int price;
    
    void display(){
        cout<<"this.speed is "<< this->speed<<endl;
        cout<<"speed is "<<speed<<endl;
        
        cout<<"this.price is "<<this->price<<endl;
        cout<<"price is "<<price<<endl;
    }
};

void thisUsing(void){

    Car c;
    c.speed = 260;
    c.price = 16;
    c.display();
    
    Car * cp = &c;
    
    cp->speed = 280;
    cp->price = 20;
    cp->display();
}


行者常至,为者常成!





R
Valine - A simple comment system based on Leancloud.