美文网首页
C++入门03 -- 类、class、struct、对象、thi

C++入门03 -- 类、class、struct、对象、thi

作者: YanZi_33 | 来源:发表于2021-08-11 13:23 被阅读0次

C++的编程规范

  • 变量名的规范参考:
    • 全局变量:g_xxx;
    • 成员变量:m_xxx;
    • 静态变量:s_xxx;
    • 常量:c_xxx;

  • 在C++中可以使用structclass来定义一个类;
  • structclass之间的区别:
    • struct的成员的默认权限是public
    • class的成员的默认权限是private
#include <iostream>

using namespace::std;

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

class Student {
public:
    int no;
    
    void study() {
        cout << "study() no = " << no <<endl;
    }
};

int main(int argc, const char * argv[]) {
    //已经创建了一个对象 已经分配了内存空间
    //person对象在栈区分配内存
    Person person1;
    person1.age = 30;
    person1.run();
    
    Person person2;
    person2.age = 33;
    person2.run();
    
    Student stu;
    stu.no = 10;
    stu.study();
    
    return 0;
}

指针访问对象成员的本质

#include <iostream>

using namespace::std;

struct Person {
    //成员变量
    int m_age;
    int m_width;
    int m_height;
    
    //成员函数
    void run() {
        cout << "run() age = " << m_age <<endl;
    }
};

int main(int argc, const char * argv[]) {
    //person对象在栈区分配内存
    Person person;
    person.m_age = 1;
    person.m_width = 2;
    person.m_height = 3;
    person.run();
    
    //定义一个指针变量 指向person对象
    Person *ptr = &person;
    ptr->m_age = 4;
    ptr->m_width = 5;
    ptr->m_height = 6;
    ptr->run();
    
    cout << sizeof(person) << endl;
    cout << "&person = " << &person << endl;
    cout << "&person.m_age = " << &person.m_age << endl;
    cout << "&person.m_width = " << &person.m_width << endl;
    cout << "&person.m_height = " << &person.m_height << endl;
    
    return 0;
}
  • 控制台调试结果如下:
Snip20210811_139.png
  • 打印结果显示person实例对象占用12个字节,其内存地址为0x7ffeefbff420,在栈区分配内存,也是第一个成员m.age的内存地址;
  • 汇编分析代码如下所示:
C++07_类`main:
    0x100002ff0 <+0>:   pushq  %rbp
    0x100002ff1 <+1>:   movq   %rsp, %rbp
    0x100002ff4 <+4>:   subq   $0x50, %rsp
    0x100002ff8 <+8>:   movl   $0x0, -0x4(%rbp)
    0x100002fff <+15>:  movl   %edi, -0x8(%rbp)
    0x100003002 <+18>:  movq   %rsi, -0x10(%rbp)
    0x100003006 <+22>:  movl   $0x1, -0x20(%rbp)
    0x10000300d <+29>:  movl   $0x2, -0x1c(%rbp)
    0x100003014 <+36>:  movl   $0x3, -0x18(%rbp)
    0x10000301b <+43>:  leaq   -0x20(%rbp), %rdi
    0x10000301f <+47>:  callq  0x100003170               ; Person::run at main.cpp:19
    0x100003024 <+52>:  leaq   -0x20(%rbp), %rax
    0x100003028 <+56>:  movq   %rax, -0x28(%rbp)
    0x10000302c <+60>:  movq   -0x28(%rbp), %rax
    0x100003030 <+64>:  movl   $0x4, (%rax)
    0x100003036 <+70>:  movq   -0x28(%rbp), %rax
    0x10000303a <+74>:  movl   $0x5, 0x4(%rax)
->  0x100003041 <+81>:  movq   -0x28(%rbp), %rax
    0x100003045 <+85>:  movl   $0x6, 0x8(%rax)
    0x10000304c <+92>:  movq   -0x28(%rbp), %rdi
  • movl $0x1, -0x20(%rbp),立即数1,可知是将1写入(rbp-0x20)内存地址,所以(rbp-0x20)是m_age的内存地址,也是实例对象person的内存地址;

  • leaq -0x20(%rbp), %rax:将person的内存地址写入rax;

  • movq %rax, -0x28(%rbp):将rax中的内容即person的内存地址写入(rbp-0x28)内存地址中,所以(rbp-0x28)就是指针变量ptr的内存地址;

  • movq -0x28(%rbp), %rax:将指针变量ptr的值即person的内存地址写入rax中;

  • movl $0x4, (%rax):将立即数4,写入person的内存地址中,即person.m_age = 4

  • movl $0x5, 0x4(%rax)person的内存地址+0x4,也就是m_width的内存地址,即person.m_width = 5

  • movl $0x6, 0x8(%rax)person的内存地址+0x8,也就是m_height的内存地址,即person.m_height = 6

  • 指针访问对象成员的本质:通过对象的内存地址+地址偏移进行访问;

this指针

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

using namespace::std;

struct Person {
    //成员变量
    int m_age;
    int m_width;
    int m_height;
    
    //成员函数
    void run() {
        cout << "run() m_age = " << m_age <<endl;
        cout << "run() m_width = " << m_width <<endl;
        cout << "run() m_height = " << m_height <<endl;
        
        cout << "run() m_age = " << this->m_age <<endl;
        cout << "run() m_width = " << this->m_width <<endl;
        cout << "run() m_height = " << this->m_height <<endl;
    }
};

int main(int argc, const char * argv[]) {
    //person对象在栈区分配内存
    Person person;
    person.m_age = 1;
    person.m_width = 2;
    person.m_height = 3;
    person.run();
   
    return 0;
}
  • person实例对象在栈区分配内存;
  • C++中类的成员函数方法在程序编译的时候,就全部存储在代码区,所以栈区对象调用代码区的函数方法时,会将栈区对象传递给函数方法;
  • 汇编代码如下:
C++07_类`main:
    0x100003050 <+0>:  pushq  %rbp
    0x100003051 <+1>:  movq   %rsp, %rbp
    0x100003054 <+4>:  subq   $0x20, %rsp
    0x100003058 <+8>:  movl   $0x0, -0x4(%rbp)
    0x10000305f <+15>: movl   %edi, -0x8(%rbp)
    0x100003062 <+18>: movq   %rsi, -0x10(%rbp)
    0x100003066 <+22>: movl   $0x1, -0x20(%rbp)
    0x10000306d <+29>: movl   $0x2, -0x1c(%rbp)
    0x100003074 <+36>: movl   $0x3, -0x18(%rbp)
    0x10000307b <+43>: leaq   -0x20(%rbp), %rdi
->  0x10000307f <+47>: callq  0x100003090               ; Person::run at main.cpp:28
    0x100003084 <+52>: xorl   %eax, %eax
    0x100003086 <+54>: addq   $0x20, %rsp
    0x10000308a <+58>: popq   %rbp
    0x10000308b <+59>: retq   
  • callq 0x100003090:调用run方法,在此之前会执行leaq -0x20(%rbp), %rdi即将实例对象person的内存地址写入rdi寄存器,为的就是在run方法中访问rdi寄存器,获取person的内存地址;

相关文章

网友评论

      本文标题:C++入门03 -- 类、class、struct、对象、thi

      本文链接:https://www.haomeiwen.com/subject/ulgqbltx.html