再谈构造函数
构造函数体赋值
前文提到,在给对象实例化时,不显式写构造函数的情况下,编译器会默认生成无参的构造函数给类中成员变量初始化
但是, 在C++中,成员变量的初始化是指在其声明时进行的赋值,这只能发生一次。
构造函数体内的赋值语句是对成员变量的赋初值,可多次进行。
const成员变量必须在声明时初始化,不能在构造函数体内赋初值
举例理解
初始化列表
初始化列表使用:初始化列表定义在构造函数的函数名和函数体之间,逗号开始,冒号隔开各个成员变量
注意点
1、初始化列表的顺序是声明的顺序
2、const对象、引用、没有默认构造自定义类型成员(必须显式传参构造)必须在初始化列表,在定义时初始化
3、初始化列表不管显不显式写编译器都会走一遍
对于自定义类型成员会调用默认构造,
对于内置类型成员可以不写(private中的成员变量给的缺省值其实就是 初始化列表 <- 正主)【有初始化列表和缺省值用 初始化列表;只有缺省值用缺省值;都没有随机值】
具体原因
- 引用类型的成员变量必须在声明时初始化,因为引用必须在创建时绑定到其引用的对象上,且之后不能更改。
- const成员变量必须在声明时初始化,因为它们必须在对象的构造期间被赋予一个常量值,并且之后不能被修改。
- 没有默认构造函数的自定义类型成员变量在初始化时需要传参,因为它们无法通过默认构造函数来初始化,必须通过参数化的构造函数来提供必要的初始值。(像是一个特殊的机器,它不能自己启动,你必须给它一些特定的零件(参数)来启动它)
explicit 关键字
谈谈内置类型变量类型转换
内置类型变量类型转换 ①影响代码的可读性,②也增加了消耗,
引出explicit 关键字,
怎么用? 在构造函数名前加关键字 explicit
作用:禁止类型转换
static 成员
概念
能计算程序中创建过多少个类对象
特征
1)静态成员属于类而非对象,存储于静态存储区。可通过类名和作用域解析运算符直接访问静态成员函数,无需通过对象。
2)静态成员变量在类外定义时无需`static`关键字,但类内声明时需加`static`。
3)静态成员函数不包含`this`指针,因此无法直接访问非静态成员。
4)静态成员遵循访问限定符(public、protected、private)的规则,其访问权限与普通成员相同。
友元
友元函数
友元函数是非成员函数,可通过在类内部声明并使用`friend`关键字授权访问类的私有和保护成员。
在类外定义了一个函数,想要访问类中的私有成员变量,这时就要用到友元
在类中实现流插入运算符的重载函数
参数顺序和操作数顺序是一致的,不能颠倒(成员函数第一个变量通常是this指针)
注意点
1. 友元函数能够访问类的私有和保护成员,但并不属于类的成员函数。
2. 友元函数声明中不能用`const`关键字;
3. 友元声明可在类的任何访问级别区域进行,不受类访问限定符影响。
4. 同一函数可被多个类声明为友元。
5. 友元函数的调用方式与普通函数相同。
友元类
友元类和友元函数类似,可以访问类中的所有成员和函数
注意点
1.友元类不要多用,因为某种程度破坏封装
2. 友元关系是单向的
如果类A是类B的友元,则A可以访问B的私有和保护成员,但反之不成立。
3. 友元关系不具有交换性
类A是类B的友元并不意味着类B自动成为类A的友元。
4. 友元关系不能传递
如果类A是类B的友元,且类B是类C的友元,这并不授予类A对类C的访问权限。
5. 友元关系不能继承
子类不会继承其基类的友元关系。
内部类
概念
如果像类A中有一个类B定义在这里,我们称 类B 为内部类
特征
1. 内部类可声明在外部类的任何访问区域(public、protected、private)。
2. 内部类可直接访问外部类的静态成员,无需通过外部类实例或类名。
3. 外部类的大小不包括内部类的成员(内部类是独立的)
内部类和外部类的关系
- 内部类作用域受外部类限制;
- 内部类自动拥有访问外部类私有成员的权限,而外部类无权访问内部类的私有成员。
匿名对象
概念
有时候我们只需要用一次某个类的方法,如果为了这个方法专门创建一个对象并给它起个名字,就显得有点麻烦。
此时引入匿名对象,匿名对象就是创建时不用给它起名字的对象。
特点
用完就消失,比如你在某一行代码中用它,到了下一行它就不存在了,系统会自动清理掉。所以,对于那些只用一次的对象,我们可以直接用匿名对象,方便快捷(适用于单次调用的场景,以避免不必要的对象命名和延长生命周期)