文章目录
1. 初始化列表
- 之前实现构造函数时,初始化成员变量主要通过函数体赋值。或者通过默认构造函数给全缺省值,构造函数初始化还有一种方式,那就是初始化列表
- C++规定,初始化列表是在函数定义和函数体中间,从冒号
:
开始,每个成员变量后面要初始化的值要放在()
里面,以逗号,
作为初始化列表数据分割的依据- 每个成员变量在初始化列表中只能出现一次,初始化列表可以看做每个成员白变量定义初始化的地方
- 引用成员变量、const修饰的成员变量、没有默认构造的类的类型变量,必须放在初始化列表初始化
- 类外面的变量也可以放在初始化列表初始化
- 当然也可以这样初始化
- C++11支持成员变量在声明时给缺省值,这个缺省值不是赋值,而是给初始化列表的
- 如果给定缺省值的成员变量在初始化列表已经有初始化值了,以初始化列表为准
- 如果给定缺省值的成员变量没有在初始化列表显示,那么默认使用该缺省值
- 初始化列表后面的函数体一般是给空的,除非特殊,可以根据需求在函数体初始化
- 尽量使用初始化列表初始化,因为不在初始化列表初始化的成员也会走初始化
- 对于没有显式在初始化列表初始化的自定义类型成员,如果也没有给缺省值,编译器会去调用这个成员类型的默认构造函数,如果默认构造函数也没有,编译器就会报错
- 初始化列表中按照成员变量在类中声明顺序进行初始化,跟成员在初始化列表出现的顺序无关,如果你不想挨打的话,还是建议声明顺序和初始化列表顺序尽量保持一致
- 练习题
- 建议:初始化要不全写在初始化列表,要不就全给缺省
2. 友元
- C++提供了一个可以突破访问类中限定符封装的成员,那就是友元。友元分为友元函数和友元类,在函数声明或函数定义前面+friend,并把友元函数放在类里面,位置随意
- 外部友元函数可以访问类的私有和保护成员,友元函数仅仅是一个声明,他不是类的成员函数
- 一般建议将友元函数放在public上面
- 一个函数可以是多个类的友元函数
- 友元类的成员函数可以是另一个类的友元函数,都可以访问另一个类的私有和保护成员
- 友元类的关系都是单向的,不具有交换性,例如A类是B类的友元,但是B类不是A类的友元
- 友元类关系不能传递,如果A类是B类的友元,B类是C类的友元,但A类不是C类的友元
- 友元虽然有时提供便利可以访问类的私有和保护成员,但是它破坏了封装,不宜多用
3. 类型转换
- C++支持内置类型隐式转换为类类型对象,需要有相关内置类型的构造函数
- 构造函数前面+explicit就不支持隐式类型转换了
- 1构造了一个A类的临时对象,然后这个临时对象的成员变量_a1 = 1,_a2 = 2,然后再将这个临时变量拷贝构造给aa1,不过编译器优化为直接构造了
- 常量引用
- 用常量100构造一个A类类型的临时对象,该临时对象的成员变量_a1 = 100, _a2 = 2,再将该临时对象绑定在A类常引用上
- 多参数
- 通过{10,20}创建一个A类的临时对象,该临时对象通过对应的构造函数后,其成员变量_a1 = 10,_a2 = 20,再将这个临时对象拷贝构造给aa2
4. static成员
- 用static修饰的成员变量,称之为静态成员变量,静态成员变量一定要在类外进行初始化
- 静态成员变量为所有类对象共享,不属于某个具体的对象,且静态成员变量不存在对象中,而是存放在静态区
- 用static修饰的成员函数,称之为静态成员函数,静态成员函数没有this指针
- 静态成员函数可以访问其他静态成员,但是不能访问非静态的,因为它没有this指针
- 非静态的成员函数,可以访问任何静态成员变量和静态成员函数
- 突破类域可以访问静态成员变量和静态成员函数,前提是静态成员是公有的
- 静态成员也是类的成员,同样也受public、private、protected访问限定符的影响
- 静态成员变量不能再声明位置给缺省值进行初始化,缺省值是给初始化列表的,而静态成员变量不属于某个对象,不走初始化列表
4.1 练习1(创建对象的个数)
4.2 练习2(求1+2+…+n)
- 题目要求不能使用乘除、if、while、for、switch等选择判断循环
4.3 练习3
5. 内部类
- 如果一个类定义在另一个类内部,那么这个类就是“内部类”,内部类是一个独立的类,它只受到外部类的类域和访问限定符影响,所以外部类定义的对象中并不包含内部类
- 内部类默认是外部类的友元
- 内部类本质就是一种封装,如果A类和B类相互关联,A类实现出来主要给B类使用,那么可以将A类设计为B类的内部类,放到private位置,那么A类就是B类的专属内部类,其他地方也用不了
6. 匿名对象
- 用类型(实参)定义出来的对象就是匿名对象,而之前定义的类型—对象名,这种是有名对象
- 匿名对象生命周期只有当前一行,一般定义一个对象临时用一下,就可以定义匿名对象
7. 对象拷贝时的编译器优化
- 编译器为了提高程序运行的效率,会对传值传参和传参作出部分优化,减少对应的拷贝
- 优化场景1
- 优化场景2
- 优化场景3
- 临时对象具有常性