1. 委托构造函数的使用场景
在实际的开发中,为了满足不同用户的不同需求,我们的一个类可能会有很多构造函数的重载版本,特别的,这些重载版本的工作内容有的比较复杂,有的比较简单,并且他们之间会有一些交叉重复的工作,即一些代码、或者数据的初始化在每个构造函数中都会去写一遍,这样显得代码特别的臃肿丑陋,委托构造函数应运而生。
2. 使用委托构造函数实例:允许在一个构造函数的初始化列表中调用另外一个构造函数,委托另外一个构造函数进行一些初始化工作
2.1 在没法进行委托构造时我们的code可能是这样的:
class foo {
public:
foo(int data) :ma(data) {}
foo(int data, int a) {
ma = data + a;
cout << "foo(int,int)" << endl;
}
foo(int data, int a, int b) :foo(data, a) {
ma = data + a;
ma += b;
cout << "foo(int,int,int)" << endl;
}
foo(int data, int a, int b, int c) :foo(data, a, b) {
ma = data + a;
ma += b;
ma += c;
cout << "foo(int,int,int,int)" << endl;
}
foo(int data, int a, int b, int c, int d) :foo(data, a, b, c) {
ma = data + a;
ma += b;
ma += c;
ma += d;
cout << "foo(int,int,int,int,int)" << endl;
}
void show() {
cout << "ma = " << ma << endl;
cout << "---------------------------" << endl;
}
int ma;
};
构造函数之间有着重复的工作、重复的代码,显示逻辑较复杂的构造函数看起来比较臃肿
2.2 当可以进行委托构造时的code:
class foo {
public:
foo(int data):ma(data){}
foo(int data, int a) {
ma = data + a;
cout << "foo(int,int)" << endl;
}
foo(int data, int a, int b) :foo(data, a) {
ma += b;
cout << "foo(int,int,int)" << endl;
}
foo(int data, int a, int b, int c) :foo(data, a, b) {
ma += c;
cout << "foo(int,int,int,int)" << endl;
}
foo(int data, int a, int b, int c, int d) :foo(data, a, b, c) {
ma += d;
cout << "foo(int,int,int,int,int)" << endl;
}
void show() {
cout << "ma = " << ma << endl;
cout << "---------------------------" << endl;
}
int ma;
};
我们拿foo(int data, int a, int b, int c, int d)
来讲,当我们使用该接口去构造一个对象时,构造与执行顺序如下:
- 先执行该接口的初始化列表,即
foo(data, a, b, c)
- 执行
foo(data, a, b, c)
,又会去调用foo(int data, int a, int b, int c)
的初始化列表 - …
- 以此类推,知道执行完最后一个构造函数
o(int data, int a)
- 最后执行
foo(int data, int a, int b, int c, int d)
的函数体部分ma += d;
。
2.3 整个过程是一个递归的过程,我们可以通过打印知道整个过程的执行顺序,需要注意的是:
- 切不可构成环装的调用过程,比如将
foo(int data, int a, int b) :foo(data, a)
改为foo(int data, int a, int b) foo(data, a, b, 1)
类似这样的语句,否则程序会抛出异常‘; - 一旦初始化列表中进行了委托构造,即调用了其他构造函数,我们就不能再在初始化列表中初始化成员变量了。
3. 总结:
- 委托构造函数的出现在特定的场景下可以减轻程序员的重复劳动力,可以增强代码美感,拒绝过于臃肿;
- 我们知道,初始化列表的执行优先于函数体的执行,所以需要明白、理清整个过程的调用过程是一个递归的过程;
- 所谓委托构造就是一个构造函数委托其他构造函数"帮忙初始化一些数据,做一些工作",并不是所有场合都适用。
- 需要注意不要生成环装的构造过程和一旦使用委托构造就不能再初始化列表中初始化成员变量。