一、构造函数的初始化列表
1、前面实现的构造函数,初始化成员变量主要使用函数体内赋值,除此之外,构造函数初始化还有一种方式,就是初始化列表,其使用方式是以一个冒号开始,接着是以一个逗号分隔的数据成员列表,每个成员变量后面可以跟一个放在括号中的初始值或表达式。
(图1)
2、每个成员变量在初始化列表中只能出现一次,语法理解上初始化列表可以认为是每个成员变量定义初始化的地方。引用成员变量,const成员变量必须在定义的时候初始化,所以必须放在成员列表。
3、引用成员变量,const成员变量, 类型变量,必须放在初始化列表进行初始化,否则会编译报错。因为引用成员变量,const成员变量,必须在定义时候初始化,如果在构造函数体内初始化的话,每个成员变量可以出现多次。
4、c++11支持在成员变量声明的位置给缺省值,这个缺省值主要是给没有显示在初始化列表初始化的成员使用的
(图2)
5、尽量使用初始化列表初始化,因为那些你不在初始化初始化的成员也会走初始化列表,如果这个成员在声明位置给了缺省值,初始化列表会用这个缺省值初始化。如果你没有给缺省值的话,对于没有显示在初始化的内置类型成员是否会初始化取决于编译器。对于没有显示在初始化列表初始化的自定义类型成员会调用这个成员类型的默认构造函数,如果没有默认构造函数会编译报错
6、初始化列表中按照成员变量在类中声明顺序进行初始化,跟成员在初始化列表出现的吸纳后顺序无关,但是建议声明顺序和初始化列表顺序保持一致,结合图3理解
(图3)
结合图表理解:
(图4)
二、类型转换
1、c++支持内置类型隐式类型转换为类类型对象,但需要有相关内置类型为参数的构造函数。
引用类型转换是要用const修饰,否则会涉及到权限放大的问题
多个参数的类型转换规定这样写
2、构造函数前面加上explicit就不再支持隐式类型转换
3、类类型的对象之间也可以隐式转化,但需要相应的构造函数支持,用
隐式类型转换的意义
三、 static成员
1、用static修饰的成员变量,称之为静态成员变量,它一定要在类外进行初始化。
2、静态成员变量为所有类对象所共享,不属于具体的对象,不存在对象中,存放在静态区
3、用static修饰的成员函数称之为静态成员函数,静态成员函数没有this指针
4、静态成员函数中可以访问其它的静态成员,但是不能访问非静态的,因为没有this指针
5、非静态的成员函数,可以访问任意的静态成员变量和静态成员函数
6、突破类域就可以访问静态成员,通过 类名::静态成员 或者 对象.静态成员 来访问静态成员变量和静态成员函数
7、静态成员也是类的成员,受访问限定符的限制
8、静态成员变量不能在声明位置给缺省值初始化,因为缺省值是构造函数初始化列表的,静态变量不属于某个对象,不会走构造函数初始化列表
四、友元
1、友元提供了一种突破类访问限定符的封装方式,友元分为:友元函数和友元类,在函数声明或者声明的前面加friend,并且把友元声明放到一个类里面。
2、外部友元函数可访问类的私有和保护成员,友元函数仅仅是一种声明,它并不是类的成员函数。
3、友元函数可以在类定义的任何地方声明,不受类访问限定符限制 。
4、一个函数可以是多个类的友元函数。
5、友元类中的成员函数都可以是另一个类的友元函数,都可以访问一个类中的私有和保护成员。
6、友元类的关系是单向的,不具有交换性,比如A类是B类的友元,但B类不能是A类的友元。
7、友元类关系不能传递,如果A是B的友元,B是C的友元,但是A不是C的友元。
8、友元可以提供便利,但是友元会增加耦合度,破坏了封装,所以友不宜多用。
五、内部类
1、如果一个类定义在另一个类的内部就叫内部类。内部类是一个独立的类,跟定义在全局相比,他只是受外部类类域限制和访问限定符限制,所以外部类定义的对象中不包含内部类。
2、内部类默认是外部类的友元。
3、内部类本质也是一种封装,当A类和B类紧密关联,A类实现出来主要就是给B类使用,就可以把A类设计为B类的内部类,如果放到private/protected位置,那么A类就是B类的专属内部类。
六、匿名对象
1、用 “类型(实参)” 定义出来的对象叫做匿名对象,之前定义的 “类型 对象名(实参)”定义出来的叫有名对象。
2、匿名对象生命周期只在当前一行,一般临时定义一个对象当前用一下即可,就可以用匿名对象