类声明定义
- 类声明class a; (仅声明不定义)
- 类定义class a{};
- 访问:类有自己的作用域,所以访问类的成员需要:类对象(.)运算符
- 定义:通过::作用域说明符指名函数属于哪个类
- 初始化成员数据:必须使用= 或 {}的形式
- 类对象:类名 + 变量名 等价为-》class / struct 类名 + 变量名
成员函数
- 成员函数声明必须在类的内部,定义可以在类内部或外部
非成员函数
-
声明和定义都在类的外部,某些和类相关的函数,尽量声明在同一个头文件
this指针 & 返回*this
- 成员函数可以直接使用成员数据,而不用通过类对象(.)
- 因为在被调用时,隐式的初始化*this形参,为调用函数的对象地址(即类对象)
- 当使用成员数据时隐式的通过this->……访问
- 虽然this指针是隐式的,但仍可以通过this显示使用
- this*是常量指针(顶层const),不允许改变this保存的地址
- return * this;对this解引用,返回成员函数调用者
const成员函数
- const应位于紧随参数列表后面
- 对于const成员函数的定义也需要指定const
- 隐式修改this的类型为 const * const this不允许改变this保存的地址,和this指向的值
- 这样做我们就可以在成员函数使用const的成员数据,this->const……,否则const无法转为非const
构造函数
- 类的成员函数由构造函数初始化,
- 没有返回类型,有可选的形参列表和函数体
- 支持重载,但不能声明为const
- 默认构造函数:不接受任何实参,仅当我们没有显示定义时,编译器才会自动创建,否则将不会创建默认构造
- 但我们可以通过 = default;生成默认构造函数,default在类内部,则默认构造为内联,在外部,为非内联
- 默认构造函数的初始化成员方式:
- 没有初始值,将默认初始化成员(复合类型是未定义的)
- 内置类型的非静态成员在没有显式初始化时,它们的值是未定义的,
- 对于指针或引用,其值是未定义的
- 对数组而言,其成员将会根据其内部类型进行初始化。
- 对结构体而言,结构体的每个成员会依赖于其类型的默认初始化规则
- 如果类类型的成员是其他类的对象,这些对象会调用它们的默认构造函数进行初始化。
- 静态成员数据需要在类外进行定义和初始化。
- 有初始值,会用初始值初始化成员
- 没有初始值,将默认初始化成员(复合类型是未定义的)
- 有时不能依赖默认构造函数:
- 当我们定义自己的默认构造,其余未被初始值列表初始化的,也都会执行默认初始化,显然更有灵活性
- 类中有内置类型 | 复合类型(& | *) | const ,可以类内初始化,或者定义自己的构造函数
- 当类中包含其他类成员,该成员没有默认构造函数,则类无法定义默认构造函数,必须自己定义构造函数
初始值列表
- :后{}前的初始值列表,为成员数据初始值,其中用逗号分隔:成员(初始值),成员(初始值),……
- 初始值和赋值:只有成员初始化列表为成员数据初始化,对于函数体内的为赋值,因为在函数体执行前,如果有未显示初始化的,会以默认构造相同的方式隐式初始化
- 成员初始化顺序:和类定义中的顺序一致,而非初始值列表的顺序初始化
访问说明符
- public:可以被类的任何外部代码访问。通常用于定义接口或需要对外部代码开放的成员。
- private:只能被类的成员函数和友元函数访问,不能被派生类的成员访问,也不能被类的外部代码访问。通常用于将类的内部实现细节隐藏起来,确保数据的封装性和安全性。
- protected受保护的成员只能被类的成员函数和友元函数访问,以及其派生类的成员访问,但不能被类的外部代码访问。
class与struct
- 都是声明类的关键字,对于定义在第一个访问说明符之前的成员,class默认为private,而struct默认为public
友元类 | 函数 & 内联 & 可变数据成员 & 默认实参
- 如果想要其他非成员的类或函数,访问private | protected成员,需要在类内声明为friend + 声明的友元类 | 函数
- 出现的位置不限,并且不受访问说明符的约束,因为友元仅仅指明了访问权限(非函数声明)
- 定义在类的内部的成员是自动inline的
- 有时我们希望修改const成员函数的数据成员,需要在变量声明前加上mutable关键字,可变数据成员永远不会是const,因此可以改变成员的值
- 成员数据不能作为默认实参
委托构造
- 使用其他的构造函数执行自己的初始化,
- 成员初始化列表只有委托本身,参数列表必须和委托的构造匹配
- 执行顺序:先执行被委托的初始化列表和函数体,然后是委托者的函数体
类类型转换
- 转换构造函数:当构造函数只有一个实参,这个实参的类型可以转换为类类型
- 仅允许一步隐式转换,不允许需要多次隐式转换的,所以要配合显示转换使用
- 本质:通过转换实际是创建了临时的类对象
- explicit构造函数声明:表示仅允许显示转换,不允许隐式转换
类的static成员
- 将成员声明为static,被访问说明符影响,可以为任何成员类型,静态成员函数不能为const
- 作用域:为整个程序,生命周期:整个程序,并且与类直接相关,不属于任何类对象
- 静态成员不包含this指针,所以不能直接使用类成员
- 作用:发生改变时,可以通知所有类对象,并且不受任何一个类对象影响
- 访问:因为不属于任何类对象,访问可以直接使用::访问,不用创建类对象
- 定义成员函数:可以在内部或外部,static不能重复,且只能在内部,也就是声明时
- 定义静态成员数据:一般情况在类的外部定义:需要加::作用域访问符,
- 从类名开始作用域都在类作用域内,所以,这条指令可以直接使用其他成员
- 类内初始化静态成员数据:可以为contexpr的静态成员提供const的类内初始值,