委托构造 和 初始化列表 都用来帮助构造函数快速初始化成员。
委托构造
C++可以依据参数列表长度、顺序和类型的不同声明多个构造函数,多个构造函数可能会做一些重复的工作,这时通过调用同一个类的其它构造函数可以消除这种重复,即 将自己的一部分工作委托给其它的构造函数完成,调用其它构造函数的这个构造函数被称之为 委托构造函数 (Delegating Constructor)
class Person {
int id;
int gender;
public:
Person(int _id, int _gender): id(_id), gender(_gender) {} // 1
Person(int _id): Person(_id, 1) {} // 2
Person(): Person(1, 1) {} // 3
}
上面的 Person 类定义了三个构造函数。
第一个构造函数有两个参数,使用 构造函数初始化列表 对类的两个成员进行初始化。
第二个构造函数只有一个参数,另一个是默认值,它将初始化任务委托给了第一个构造函数。
第三个构造函数两个参数都是默认值,它也将初始化任务委托给了第一个构造函数。
委托构造 和 初始化列表 的位置都位于参数列表的后面,一个构造函数使用委托构造后就不能继续初始化其它的参数了,其它的初始化操作应该放在方法实现中用 赋值 的方式完成。
两个构造函数相互委托就会实现 委托环 导致编译报错,应该避免这种情况。
try ... catch
可以捕获委托构造时被委托构造函数抛出的异常:
class Person {
Person(int _id, int _gender): id(_id), gender(_gender) {}
Person(int _id): try Person(_id, 1) {
//...
} catch (/*...*/) {
//...
}
}
另外,对于一个继承自父类的类,自己新增的构造函数也可以委托父类的构造函数:
class Shape {
int edges;
Shape(int _edges): edges(_edges) {}
}
class Square: public Shape {
int w;
Square(int _edges, int _w): Shape(_edges) {
w = _w;
}
}
初始化列表
构造函数中的初始化列表用来对实例的属性快速赋值,这一般与在构造函数实现中逐个赋值是等价的:
class Person {
int _id;
int _gender;
// Person(int _id, int _gender): id(_id), gender(_gender) {}
Person(int _id, int _gender) {
id = _id;
gender = _gender;
}
}
然而对于不能赋值的成员,例如 const 成员或者引用类型的成员,只能使用初始化列表进行初始化。
对多个成员进行初始化时,编译器按照成员的声明顺序,而不是在初始化列表中的顺序进行初始化。
评论区