- 数据抽象:是一种依赖于接口和实现分离的变成技术。
- 封装:分离接口(用户所能执行的操作)和实现(数据成员、实现接口的函数体、私有函数)
7.1 定义抽象数据类型
7.1.2 定义改进的Sales_data类
- 成员函数:声明必须在类内部,但定义可在类内或外,定义在类内部的函数是隐式的inline函数。
- this:成员函数通过一个名为this的额外的隐式参数来访问调用它的那个对象,当我们调用一个成员函数时,用请求该函数的对象地址初始化this。this是一个常量指针。
- 常量成员函数:参数列表后带const的函数叫常量成员函数,它可将this设置为指向常量的指针,使得常量对象可访问常量成员函数,但不可写入新值;若以引用形式返回*this,则返回类型是常量引用。
- 定义在外部的成员函数:范围解析运算符 :: 来定义。
7.1.4 构造函数
- 合成的默认构造函数:会尽可能使用类内初始值初始化数据成员,当类不存在任何构造函数时,编译器创建默认构造函数(被称为合成的默认构造函数);既需要其他形式又需要合成的默认构造函数,可在默认构造函数的参数列表后面加上= default。
7.1.5 拷贝、赋值和析构
- 的动态内存:当类需要分配类对象之外的资源时,合成的版本常常会失效;需要动态内存的类应该使用vector或string对象管理存储空间,避免分配和释放内存带来的复杂性
7.2 访问控制与封装
7.2.1 友元
- 友元:允许其他类或函数访问非公有成员,则可在类的开头用friend关键字将其声明为友元;友元的声明仅仅限定了权限,可在真正的函数声明之后;友元函数可以定义在类的内部,但在类的外部仍然需要提供相应的声明使得函数可见
7.3 类的其他特性
7.3.1 类成员再探
- 内联函数:定义在类内部的成员函数是自动inline的。
- 重载const:根据是否是常量对象,决定调用是否是常量版本的成员函数。
7.3.3 类类型
- 类的声明:每个类定义唯一的类型。仅声明不定义叫做前向声明:类在声明之后、定义完成之前是不完全类型,可以定义其指针或引用,作为函数的参数或返回值;只有当类全部完成后类才算被定义,所以类的成员中不能包含自己,但可以出现指针或引用。
7.4 类的作用域
- 访问类成员:使用this->或类名::可强制访问类成员,无视作用域的名字查找规则;无类名加::表示全局对象。
7.5 构造函数再探
7.5.1 构造函数初始值列表
- 成员初始化:若成员是const、引用、无默认构造函数的类,必须通过初始值列表将其初始化。
- 初始化顺序:与类中定义的顺序一致,不受初始值列表中顺序影响。
7.5.5 聚合类
- 聚合类:所有成员public、未定义构造函数、无类内初始值、无基类或virtual函数;使用花括号初始化,花括号内的初始值顺序与声明顺序一致。
7.5.6 字面值常量类
- 字面值常量类:数据成员都是字面值类型的聚合类;或数据成员都是字面值类型、至少含有一个constexpr构造函数、类内初始值是常量表达式或拥有自己的constexpr构造函数、使用析构函数的默认定义。
- constexpr构造函数:为保证构造函数的不包含返回语句,和constexpr函数唯一可执行语句即返回函数,其函数体一般为空。
7.6 类的静态成员
- 静态成员:独立于任何对象之外,不包含this指针;静态成员函数不能声明为const,也不能在内部使用this指针。
- 静态数据成员:必须在类的外部定义和初始化,方式和类外部定义成员函数类似;若静态数据成员为constrexpr类型,且其只限于编译器替换值的使用场景,则可以在类内定义,否则必须在类外再重新定义。
- 静态成员的优势:类内可包含自身类型的静态数据成员,但普通成员只能是指针或引用;静态成员可以作为默认实参,非静态数据成员的值属于对象的一部分,不能作为默认实参。