美文网首页
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