委派构造函数可以减少构造函数的书写量:
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); }
目标函数中抛出异常,可以在委派构造函数中捕获。