什么是构造函数(constructor)
每个类都分别定义了它的对象被初始化的方式,类通过一个或几个特殊的成员函数老控制其对象的初始化过程,这些函数叫做构造函数。
构造函数的特点
- 构造函数的名字和类的名字相同
- 构造函数没有返回值
- 一个类可以包括多个构造函数,不同的构造函数之间必须在参数数量或参数类型上有所区别
- 构造函数不能被声明为const的
- 对于创建一个const对象,直到构造函数完成初始化的过程,对象才真正取得其常量属性。
- 类的常量数据成员的在构造函数中初始化使用初始值列表初始化(在函数体中是对常量成员的赋值,不是初始化,因此会导致错误)的方法
- 同理,引用类的数据成员也必须初始化,规则同上。
- 使用初始化列表初始化成员时,初始化的顺序与它们在类定义中的出现顺序一致,构造函数初始值列表中初始值的顺序的前后位置关系不会影响实际的初始化顺序。数据成员的初始化在函数体开始前就已完成
- 建议使用构造函数初始值:在很多类中,初始化和赋值的区别事关底层效率的问题:前者直接初始化数据成员,后者先初始化再赋值;再者,一些数据成员必须被初始化,如const、引用、未提供默认构造函数的类
默认构造函数
定义
如果我们的类没有显示地定义任何构造函数,那么编译器会为我们隐式地定义一个默认构造函数。
编译器创建地默认构造函数又称为合成地默认构造函数。初始化规则如下:
- 如果存在类内地初始值,用其来初始化成员:C++11规定,可以为数据成员提供一个类内初始值,创建对象时可以用于初始化数据成员。类内初始化就是在定义成员变量的同时将其初始化。
- 否则,默认初始化该成员:内置类型的变量未被显式初始化,值由定义的位置决定,定义于任何函数体之外的变量被初始化为0;定义于函数体内部的内置类型变量(局部变量,包括类中的成员变量)将不被初始化。
=default的含义
在C++11中,如果我们需要默认的行为,那么可以通过在参数列表后面写上 =default 来要求编译器生成构造函数。=default 既可以和声明一起出现在类的内部,也可以作为定义出现在类的外部。和其他函数一样,如果=default出现在类的内部,则默认构造函数是内联的。如果在类的外部,则默认情况下不是内联的。
默认初始化发生的时间
当对象被默认初始化或值初始化时自动执行默认构造函数。默认初始化在以下情况发生:
- 当我们在块作用域内不适用任何初始值定义一个非静态变量或者数组时
- 当一个类本身含有类类型的成员且使用合成的默认构造函数时
- 当类类型的成员没有在构造函数初始值列表中显式地初始化时
值初始化在以下情况发生:
- 在数组初始化的过程中如果我们提供的初始值数量少于数组的大小时
- 当我们不使用初始值定义一个局部静态变量时
- 当我们通过书写形如 T() 的表达式显式地请求值初始化时
委托构造函数(delegating constructor)
一个委托构造函数使用它所属类的其他构造函数执行它自己的初始化过程。
一个委托构造函数有一个成员初始值的列表和一个函数体。在委托构造函数中,成员初始值列表只有一个唯一的入口,就是类名本身。与其他成员初始值一样,类名后面紧跟圆括号括起来的参数列表,参数列表必须与类中另外一个构造函数匹配。
|
|
当一个构造函数委托给另一个构造函数时,受委托的构造函数的初始值列表和函数体被依次执行。假如函数体包含有代码的话,将先执行这些代码,然后控制权才会交还给委托者的函数体。