c++11 委派构造函数

委派构造函数可以减少构造函数的书写量:

class Info {
public:
 Info() : type(1), name('a') {
  InitRest();
 }

 Info(int i) : type(i), name('a') {
  InitRest();
 }

 Info(char e) : type(1),, name(e) {
  InitRest();
 }

private:
 void InitRest() { //其他初始化 }
 int type;
 char name;
};

每个构造函数都需要初始化列表来初始化成员type和name,且都调用了相同的函数InitRest,存在重复。

而在C++11中,可以使用委派构造函数来简化代码,如下:

class Info {
public:
 Info() { InitRest(); }  //称为目标构造函数(被调用)
 Info(int i) : Info() { type = i; }  //委派构造函数(调用者)
 Info(char e) : Info() { name = e; }

private:
 void InitRest() { // other int }
 int type {1};
 char name {'a'};  
};

委派构造函数只能在函数体内为type,name等成员赋值,因为委派构造函数不能有初始化列表。C++中,构造函数不能同时使用委派和初始化列表。

初始化列表的初始化总是先于构造函数完成,作一下修改:

class Info {
public:
 Info() : Info(1, 'a') {}
 Info(int i) : Info(i, 'a') {}
 Info(char e) : Info(1, e) {}

private:
 Info(int i, char e) : type(i), name(e) {} //将初始化动作放在一个通用的构造函数里
 int type;
 char name; 
};

在构造函数比较多时,可以有不止一个委派构造函数,目标函数也可以是委派构造函数,可以在委派构造函数中形成链状的委派构造关系。

class Info {
public:
 Info() : Info(1) {}
 Info(int i) : Info(i, 'a') {}  //可以委派成链状,但不能形成环。
 Info(char e) : Info(1, e) {}

private:
 Info(int i, char e) : type(i), name(e) {}
 int type;
 char name;
};

委派构造函数的应用:

1.模板:

#include <list>
#include <vector>
#include <deque>

using namespace std;

class TDConstructed {
 template<class T>
 TDConstructed(T first, T last) : l(first, last) {}

 list<int> l;

public:
 TDConstructed(vector<short> & v) : TDConstructed(v.begin(), v.end()) {}
 TDConstructed(deque<int> & d) : TDConstructed(d.begin(), d.end()) {}
}

以上定义了一个构造函数模板,通过两个委派构造函数的委托,构造函数模板被实例化。

2. 异常处理:

#include <iostream>
using namespace std;

class DCExcept(double d) try : DCExcept(1, d) {
   cout << "Run the body." << endl;   
} catch(...) {
  cout << "caught exception." << endl;
}

private:
 DCExcept(int i, double d) {
   cout << "going to throw!" << endl;
   throw 0;
 }

 int type;
 double data;
};

int main() {
 DCExcept a(1.2);
}

目标函数中抛出异常,可以在委派构造函数中捕获。