美文网首页
C++: 类(上)

C++: 类(上)

作者: sajiner | 来源:发表于2018-10-22 16:19 被阅读6次

    简介
    1、C++中可以使用struct、class来定义一个类
    2、 struct和class的区别:

    • struct修饰的类默认成员权限是public
    • class修饰的类默认成员权限是private
    /// struct修饰
    struct Person {
        int m_id;
        int m_age;
        int m_height;
        void run() {
            cout << "Person: run()" << endl;
            cout << "person.m_id" << m_id << endl;
            cout << "person.m_age" << m_age << endl;
            cout << "person.m_height" << m_height  << endl;
        }
    };
    /// class修饰
    class Person {
        int m_id;
        int m_age;
        int m_height;
        void run() {
            cout << "Person: run()" << endl;
            cout << "person.m_id" << m_id << endl;
            cout << "person.m_age" << m_age << endl;
            cout << "person.m_height" << m_height  << endl;
        }
    };
    

    3、如何创建对象和访问类的成员

    /// 方式一:直接创建,通过对象访问
    int main(int argc, const char * argv[]) {
        Person person; /// 在栈空间分配了内存给person,不需要手动释放内存
        person.m_id = 10;
        person.m_age = 10;
        person.m_height = 30;
        person.run();
        cout << person.m_age << endl;
        cout << person.m_height << endl;
        
        return 0;
    }
    /// 方式二:new创建,通过指针访问
    int main(int argc, const char * argv[]) {
        Person *pPerson = new Person();
        pPerson->m_height = 30;
        pPerson->m_age = 10;
        pPerson->run();
        cout << pPerson->m_age << endl;
        cout << pPerson->m_height << endl;
    
        delete person;
        return 0;
    }
    /// 方式三:malloc创建,通过指针访问
    int main(int argc, const char * argv[]) {
        Person *pPerson = (Person *)malloc(sizeof(Person));
        pPerson->m_height = "jack";
        pPerson->m_age = 10;
        pPerson->run();
        cout << pPerson->m_height << endl;
        cout << pPerson->m_age << endl;
        free(pPerson);
        return 0;
    }
    

    注意:上述代码中,person对象和pPerson指针都是存在栈空间,由系统自动分配内存和释放;而newmalloc出来的person对象在堆中,需要手动释放,new对应deletemalloc对应free,两者不能互换。
    4、对象的内存布局
    思考:如果类中有多个成员变量,对象的内存是如何分布的?

    int main(int argc, const char * argv[]) {
        Person person;
        person.m_id = 1;
        person.m_age = 2;
        person.m_height = 3;
    
        cout << &person << endl;  /// 0x7ffeefbff510
        cout << &person.m_id << endl;  /// 0x7ffeefbff510
        cout << &person.m_age << endl; /// 0x7ffeefbff514
        cout << &person.m_height << endl;  /// 0x7ffeefbff518
        cout << sizeof(person) << endl;  /// 12
        
        getchar();
        return 0;
    }
    

    由打印结果可知:对象的内存大小由类中的成员变量的所占大小决定,内存分布按着成员变量的先后顺序依次增大,且对象的地址值与首成员变量的地址值一样

    思考:如下代码,最后打印出来的结果是什么

    int main(int argc, const char * argv[]) {
        Person person;
        person.m_id = 1;
        person.m_age = 2;
        person.m_height = 3;
        
        Person *pPerson = (Person *)&person.m_age;
        pPerson->m_id = 30;
        pPerson->m_age = 40;
        
        person.run(); /// 结果:m_id=1,m_age=30,m_height=40
        
        getchar();
        return 0;
    }
    
    内存布局图.png

    由内存分析图:

    • &person = &person.m_id&person + 4 = &person.m_age&person + 8 = &person.m_height,即类中成员变量的内存地址是连续且递增的
    • pPerson指针指向person.m_age的内存地址,即创建的person对象地址值即为person.m_age的地址值,pPerson对对象的m_id赋值就相当于修改了原person对象的m_age内存地址所存储的值,即是m_age的值,同理为pPerson->m_age赋值就是修改原person对象的m_height内存地址所存储的值
    • 由上可知,指针访问对象成员的本质就是(对象的地址加上偏移0或者上一个成员变量所占内存的大小)所指向的内存

    5、this

    • this是指向当前对象的指针
    • 对象在调用成员函数的时候,会自动传入当前对象的内存地址
    • this访问成员变量只能通过this->m_id访问,不能使用this.m_id
    • 成员函数内部可以省略this
    class Person {
        int m_id;
        int m_age;
        int m_height;
        void run() {
            cout << "Person: run()" << endl;
            cout << "person.m_id" << m_id << endl; /// this->m_id可以省略this
            cout << "person.m_age" << m_age << endl; /// this->m_age可以省略this
            cout << "person.m_height" << m_height  << endl; /// this->m_height可以省略this
        }
    };
    

    6、C++中的封装
    体现是成员变量私有化,提供公共的getter和setter给外界取访问成员变量

    class Person {
        int m_age;
    
     public:
        int getAge() {
            return this->m_age;
        }
        
        void setAge(int age) {
            this->m_age = age;
        }
    };
    

    7、内存空间的布局
    每个应用都有自己独立的内存空间,其内存空间一般都有以下几大区域

    • 代码段(代码区)
      用于存放代码
    • 数据段(全局区)
      用于存放全局变量等
    • 栈空间
      每调用一个函数就会给它分配一段连续的栈空间,等函数调用完毕后会自动回收这段栈空间
      特点:自动分配和回收
    • 堆空间
      需要主动去申请和释放

    堆空间

    • 在程序运行过程,为了能够自由控制内存的生命周期、大小,会经常使用堆空间的内存
    • 堆空间的申请\释放
      malloc \ free
      new \ delete
      new[] \ delete[]
    • 堆空间申请成功后,会返回那一段内存空间的地址
    • 申请和释放必须是1对1的关系,不然可能会存在内存泄露

    堆空间的初始化

    堆空间的初始化.png

    memset函数是将较大的数据结构(比如对象、数组等)内存清零的比较快的方法

    int main(int argc, const char * argv[]) {
        Person peron;
        peron.m_id = 1;
        peron.m_age = 2;
        peron.m_height = 3;
        memset(&peron, 0, sizeof(peron));
    
        Person persons[] = { {1, 2, 43}, {3, 4, 5}, {12, 32, 45} };
        memset(persons, 0, sizeof(persons));
    
        return 0;
    }
    

    对象的内存
    对象的内存可以存储于3种地方:

    • 全局区
    • 栈区
    • 堆区
    Person g_person; /// 全局区
    int main(int argc, const char * argv[]) {
        Person person; /// 栈区
        Person *pPerson = new Person; /// 堆空间
        return 0;
    }
    

    相关文章

      网友评论

          本文标题:C++: 类(上)

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