c++的学习与总结(2.类和对象上) 一、类的基本属性1. 类的定义类是用class关键字定义的用户自定义类型可以包含成员变量和成员函数。2. 代码示例class A { // 成员变量 int _a; // 成员函数 void func() {} };3. 类的成员3.1成员变量(类内部的变量)成员变量一般加_前缀与函数参数做区分3.2 成员函数(类内部的函数)在类体内定义的成员函数编译器会隐式视为内联函数但最终是否内联由编译器决定4.类的内存分配成员类型是否占对象内存说明成员变量占创建对象时分配对齐规则与结构体相同成员函数不占代码存在代码段对象中不存储空类无成员变量占 1 字节用于占位标识对象存在5. 类域类域用于区分不同类之间的成员头文件里放类的声明在对应的.cpp文件中定义成员函数时需要用类名::指明函数属于哪个类 .例如void Stack::init() { }6. 与struct 的区别struct在 C 中也可以定义类区别class默认访问权限为privatestruct为public二、对象创建1. 概念类名 变量名2. 代码示例A a;三、访问限定符public / private1. 概念决定这个成员能不能被外界访问2. 代码示例class A { public: void func(); // 类外可调用 private: int _a; // 类外不可访问 };3. 特性public类内外都能访问通常放成员函数private只有类内部能访问通常放成员变量protected目前和private一样继承时才有区别限定符作用域从它开始到下一个限定符结束class默认privatestruct默认public4. 补充一般public写的是成员函数private写的是成员变量四、构造函数1. 概念函数名与类名相同无返回值用于初始化类的对象2. 代码示例class Date { public: Date(int y, int m, int d) { _year y; _month m; _day d; } private: int _year; int _month; int _day; };3. 特性可以重载可以有缺省参数一旦用户写了任何构造系统不再生成默认构造调用默认构造不加括号Date d;三种默认构造类型形式何时生成/调用无参构造Date() {}用户显式写出全缺省构造Date(int y1, int m1, int d1) {}用户显式写出编译器默认生成用户没写任何构造时对内置类型不初始化值不确定对自定义类型调用其默认构造注意在使用默认构造时用Data tData();这样的形式初始化时会调用变量的值初始化比如int为0自定义变量调相应的初始构造用Data t;这样的形式会用随机值。若使用自己的构造函数有缺省值的话Data t;这样的形式会用缺省值五、析构函数1. 概念~类名无返回值无参数是对象的销毁2. 代码示例class A { public: ~A() { // 释放资源 } };3. 特性没有动态内存时默认析构足够当有动态内存时要手动释放析构顺序与构造相反后创建的先销毁六、初始化列表1. 概念冒号开头逗号分隔在构造函数体之前执行2. 代码示例class Date { public: Date(int y, int m, int d) : _year(y), _month(m), _day(d) {} private: int _year; int _month; int _day; };3. 特性初始化顺序按声明顺序建议列表顺序与之相同易错点效率比函数体内赋值高成员类型是否必须在初始化列表初始化原因const成员必须const变量只能初始化不能赋值引用成员必须引用必须绑定到对象且不能重新绑定没有默认构造的对象成员必须无法在函数体内构造没有默认构造可用普通内置类型可选可以在函数体内赋值但列表效率更高七、this 指针1. 概念指向当前对象的指针2. 代码示例class A { public: void set(int a) { this-_a a; } private: int _a; };3. 特性区分同名参数和成员变量this-_a a;this是指针常量不能修改指向静态成员函数没有this每个非静态成员函数都有一个隐含的this指针指向调用对象八、拷贝构造1. 概念构造函数的重载参数是同类对象的const引用用已有对象初始化新对象时调用2. 代码示例class Date { public: Date(const Date d) { _year d._year; _month d._month; _day d._day; } private: int _year; int _month; int _day; };3. 特性必须用引用否则无限递归如果不写编译器生成默认拷贝构造浅拷贝写法是否调用拷贝构造说明Date d2(d1);调用直接初始化Date d2 d1;调用拷贝初始化编译器可能优化为直接构造func(d1)传值参数调用实参拷贝给形参return d1返回值调用局部对象拷贝给返回值可能被 RVO 优化掉Date d2; d2 d1;不调用这是赋值重载不是拷贝构造九、浅拷贝 vs 深拷贝1. 概念浅拷贝拷贝地址深拷贝拷贝内容2. 代码示例// 浅拷贝默认 // String s2(s1); // s1 和 s2 的 _data 指向同一块内存 // 深拷贝 String(const String s) { _data new char[strlen(s._data) 1]; strcpy(_data, s._data); }3特性对比项浅拷贝深拷贝实现方式编译器默认生成用户手动实现拷贝内容逐字节拷贝成员变量的值拷贝指针指向的内容并开辟新内存指针成员只拷贝地址指针的值拷贝指针指向的数据新对象拥有独立内存多个对象的关系多个对象指向同一块内存每个对象有自己的内存互不干扰资源释放多次释放同一块内存 → double free各自释放自己的内存安全适用场景没有动态内存成员的简单类类中有指向动态内存的指针成员如char*、int*是否可依赖默认不可依赖有指针时必须自己实现