1. 委托构造函数的使用场景
// 场景1 class Box1 { public: Box1() : m_l(0), m_h(0), m_w(0) {} Box1(int l) : m_l(l), m_h(0), m_w(0) {} Box1(int l, int h) : m_l(l), m_h(h), m_w(0) {} Box1(int l, int h, int w) : m_l(l), m_h(h), m_w(w) {} public: int m_l; int m_h; int m_w; };
缺点:每个构造函数都有重复的成员变量的初始化语句
// 场景2 class Box2 { public: Box2() { init(0, 0, 0); } Box2(int l) { init(l, 0, 0); } Box2(int l, int h) { init(l, h, 0); } Box2(int l, int h, int w) { init(l, h, w); } // 初始化函数 void init(int l, int h, int w) { m_l = l; m_h = h; m_w = w; } public: int m_l; int m_h; int m_w; };
初始化交给一个普通成员函数,该成员函数无法使用简洁的初始化列表语句,需要额外给类增加一个初始化函数。
2. 委托构造函数语法
C++11 增加了委托构造函数,委托构造函数也叫做委派构造函数,指的是,将当前构造函数的初始化任务交给其他的构造函数来完成。
委托构造函数使用的一般步骤是什么?
- 先找一个能够将所有的成员变量进行初始化的构造函数、或者更加通用的构造函数,当做【目标构造函数】目标构造函数实际是执行初始化任务的构造函数。
- 将其他的构造函数的初始化任务交由该目标函数进行初始化。
委托构造函数的优点:代码更加清晰、构造函数的行为更加正确
class Box3 { public: // 前三个构造函数,叫做委托构造函数 Box3() : Box3(0, 0, 0) { cout << "委托构造函数 Box3()" << endl; } Box3(int l) : Box3(l, 0, 0) { cout << "委托构造函数 Box3(int l)" << endl; } Box3(int l, int h) : Box3(l, h, 0) { cout << "委托构造函数Box3(int l, int h) " << endl; } // 目标构造函数 Box3(int l, int h, int w) : m_l(l), m_h(h), m_w(w) { cout << "目标构造函数" << endl; } public: int m_l; int m_h; int m_w; }; void test01() { // 当调用一个委托构造函数进行对象构建时,其构造函数调用的顺序是什么? // 首先,调用目标构造函数进行初始化 // 然后,再调用委托构造函数本身进行初始化 Box3 box; }
3. 委托构造函数使用注意
- 委托构造函数不能同时使用目标构造函数、初始化列表对对象进行初始化。原因:初始化列表执行先于构造函数。如果目标构造函数和初始化列表同时初始化同一个变量,可能造成问题。非委托构造函数可以使用初始化列表。
- 不允许委托多个目标构造函数执行初始化任务,委托构造函数委托的目标构造函数能够进行完整初始化。
- 委托构造函数可以将初始化任务交给另外一个委托构造函数,但是要注意不能出现闭环。
注意事项一的示例代码:
class Box4 { public: // 前三个构造函数,叫做委托构造函数 // Box4() : Box4(0, 0, 0), m_l(100) { } Box4(int l) : Box4(l, 0, 0) {} Box4(int l, int h) : Box4(l, h, 0) {} // 目标构造函数 Box4(int l, int h, int w) : m_l(l), m_h(h), m_w(w) {} public: int m_l; int m_h; int m_w; };
注意事项二的示例代码:
class Box5 { public: // 以下注释代码编译错误 // Box5(int l, int h, int w) : Box5(l), Box5(h, w){} Box5(int l) : m_l(l) {} Box5(int h, int w) : m_h(h), m_w(w) {} public: int m_l; int m_h; int m_w; };
注意事项三的示例代码:
class Box6 { public: // 一定要注意:避免出现委托构造链表的闭环 //Box6() : Box6(0){ } //Box6(int l) : Box6(l, 0) {} //Box6(int l, int h) : Box6(l, h, 0) {} //Box6(int l, int h, int w) : Box6(){} public: int m_l; int m_h; int m_w; };