共计 2479 个字符,预计需要花费 7 分钟才能阅读完成。
类
成员函数
成员函数的声明必须在类的内部,定义既可以在类的内部也可以在类的外部,成员函数也是一个块
类外定义的形式为:
返回值类型 类名:: 成员函数名(参数列表){}
引入 this
成员函数通过 this 的额外的隐式参数来访问调用它的那个对象,当我们调用一个成员函数时,用请求该函数的对象地址初始化 this,任何定义为 this 名的参数或变量的行为都是非法的,this 是一个常量指针,不允许改变 this 中保存的地址
引入 const 成员函数
紧随参数列表之后的 const 关键字,作用是修改隐式 this 指针的类型,表示 this 是一个指向常量的指针,像这样使用 const 的成员函数被称作常量成员函数
常量对象,常量对象的引用以及指针都只能调用常量或常量成员函数
类相关的非成员函数
如果函数在概念上属于类但不定义在类中,一般与类声明在同一个头文件中
构造函数
初始化类对象的数据成员,无论何时只要类的对象被创建,就会执行构造函数,名字和类名相同,没有返回类型,不能被声明为 const
如果没有显式定义构造函数,编译器会为我们隐式定义一个默认构造函数,又被称作 合成的默认构造函数,如果存在类内的初始值,用它来初始化成员,否则,默认初始化该成员
如果没有在构造函数的初始值列表中显式地初始化成员,则该成员在构造函数整体之前执行默认初始化,如果成员是 const 成员或者引用,必须将其初始化,当成员属于某种类类型且该类没有定义默认构造函数时,也必须将这个成员初始化
=default
如果定义了其他构造函数,仍想让编译器合成默认的构造函数,可以通过在参数列表后面写上 =default 来要求编译器生成默
认构造函数,=default 既可以和声明一起
出现在类内部,也可以作为定义出现在类的外部,在类的内部,默认构造函数是内联的,不在内部,默认情况下不是内联的
构造函数初始值列表
负责为新创建的对象的一个或几个数据成员赋初值,构造函数初始值是成员名字的一个列表,每个名字后面紧跟括号括起来的(或者在花括号内的)成员初始值,不同成员的初始化通过逗号分隔开来
访问控制与封装
public:成员在整个程序内可以被访问
private: 成员可以被类的成员函数访问,不能被使用该类的代码访问
使用 class 或 struct 关键字
struct 默认访问权限为 public,class 默认访问权限是 private
友元
类允许其他类或函数访问它的非公有成员的方法是:令其他类或函数称为它的友元,增加一条以 friend 关键字开头的函数声明语句只能出现在类定义的内部,不是类的成员也不受它所在区域访问控制级别的约束
重载成员函数
可变数据成员
可以通过在变量的声明中加入 mutable 关键字来实现修改类的某个数据成员,即使是在一个 const 成员函数内
返回 *this 的成员函数
一个 const 成员函数如果以引用的形式返回 *this,那么它的返回类型将是一个常量引用
基于 const 的重载
类类型
可以把类名作为类型的名字使用,从而直接指向类类型,也可以把类名跟在关键字 struct 或 class 后
类的声明
class 类名;
这种声明有时候被称作前向声明
名字查找与类的作用域
名字查找 过程:
1、在名字所在块中寻找声明语句,只考虑在名字使用之前出现的声明
2、如果没找到,继续查找外层作用域
3、如果最终没有找到匹配的声明,则报错
编译器处理完类中的全部声明后才会处理成员函数的定义
在类中,如果成员使用了外层作用域中某个名字,而改名字代表一种类型,则类不能在之后重新定义该名字
成员定义中普通块作用域的名字查找 过程:
1、在成员函数内查找该名字的声明,只在函数使用之前出现的声明才被考虑
2、如果在成员函数内没有找到,则在类内继续查找,类的所有成员都可以被考虑
3、如果类内也没有找到该名字的声明,在成员函数定义之前的作用域内继续查找
如果一个构造函数为所有参数都提供了默认实参,则它实际上也定义了默认构造函数
委托构造函数
使用它所属类的其他构造函数执行自己的初始化过程,把自己的一些(或全部)职责委托给了其他构造函数
有一个成员初始值列表和一个函数体
成员函数列表只有一个唯一的入口,就是类名本身,类名后面紧跟圆括号括起来的参数列表,参数列表必须与类中另外一个构造函数匹配
抑制构造函数定义的隐式转换
通过将构造函数声明为 explicit 加以阻止,将只能以直接初始化的形式使用,编译器不会在自动转换过程中使用该构造函数
聚合类
使用户可以直接访问其成员,并且具有特殊的初始化语法形式
满足以下条件时,说此类是聚合类:
1、所有成员都是 public 的
2、没有定义任何构造函数
3、没有类内初始值
4、没有基类,也没有 virtual 函数
可以提供一个花括号括起来的成员初始值列表来初始化聚合类的数据成员
字面值常量类
数据成员都是字面值类型的聚合类是字面值常量类,或者满足以下条件:
1、数据成员都是字面值类型
2、类必须至少含有一个 constexpr 构造函数
3、如果一个数据成员含有类内初始值,则内置类型成员的初始值必须是一条常量表达式;或者如果成员属于某种类类型,则初始值必须使用成员自己的 constexpr 构造函数
4、类必须使用析构函数的默认定义,该成员负责销毁类的对象
constexpr 构造函数可以声明称 =default 的形式或者是删除函数的形式,否则 constexpr 函数体一般来说应该是空的
类的静态成员
声明静态成员
通过在成员的声明之前加上关键字 static 使得其与类关联在一起,类的静态成员存在于任何对象之外,对象中不包含任何与静态数据成员有关的数据,静态成员函数也不与任何对象绑定在一起,不包含 this 指针,不能声明为 const
使用类的静态成员
通过作用域运算符直接访问静态成员
定义静态成员
可以在类的内部也可以在类的外部定义静态成员函数,在类的外部定义静态成员时,不能重复 static 关键字,只出现在类的内部声明语句中,一个静态数据成员只能定义一次
静态成员的类内初始化
通常情况下,类的静态成员不应该在类的内部初始化,可以为静态成员提供 const 整数类型的类内初始值,要求静态成员必须时字面值常量类型的 constexpr