在c++11中有一个新特性,就是委托构造函数。委托构造函数可以使用当前类的其他构造函数来帮助当前构造函数初始化。换而言之,就是可以将当前构造函数的部分(或者全部)职责交给本类的另一个构造函数。
我们先看看委托构造函数与普通构造函数的相同点与不同点。
相同点:
两者都有一个成员初始值列表与一个函数体
不同点:
委托构造函数的成员初始值列表只有一个唯一的参数,就是构造函数(当然不能是当前的构造函数)
当被委托的构造函数的函数体中如果有代码,那么会先执行完函数体的代码,才会回到委托构造函数。在这里我们可以理解为一次函数调用(当然两者还是有些区别的)。我们来看看示例代码
#include <iostream>
#include <string>
class A{
private:
int _a;
std::string _s;
public:
// 普通构造函数
A(std::string s, int a) : _a(a), _s(s){
std::cout << "执行 普通构造函数 函数体" << std::endl;
}
// 委托构造函数
A(int a): A("测试A(int a)", a){
std::cout << "执行 委托构造函数A(int a) 函数体" << std::endl;
}
A(std::string s): A(s, 100){
std::cout << "执行 委托构造函数A(std::string s) 函数体" << std::endl;
}
A(): A("测试A()", 4) { }
A(std::ostream &out): A(){
out << "我就是打酱油的\n";
}
// 打印对象内容
void display() const{
std::cout << "---------------------" << std::endl;
std::cout << "s = " << _s << std::endl;
std::cout << "a = " << _a << std::endl;
std::cout << "---------------------" << std::endl;
}
};
int main()
{
A a("测试A(std::string s, int a)", 1);
a.display();
A b(2);
b.display();
A c("测试A(std::string s)");
c.display();
A d(std::cout);
d.display();
return 0;
}
通过这一份代码,我们很容易就明白委托构造函数的作用。我们接下来看几个错误的例子。
Case 1:成员初始化列表
class B{
int _a;
std::string _s;
B(int a): _a(a){ }
B(std::string s): _s(s){ }
// 错误示例
// 委托构造函数的成员初始化列表中,只能有一个构造函数
// 且不能是当前构造函数
// 错误1:成员初始化列表中含有其他成员变量的初始化
B(int a, std::string s): _a(a), B(s){ }
B(int a, std::string s): B(a), _s(s){ }
// 错误2:成员初始化列表中含有多个构造函数
B(int a, std::string s): B(a), B(s){ }
};
Case 2: 循环调用
class B{
private:
int _a;
std::string _s;
public:
B(int a): B("Test") {
_a = a;
}
B(std::string s): B(100){
_s = "你是执行不到我这里的!!!";
}
};
这一份代码是可以通过编译的,但是却无法运行。因为一旦初始化,无论执行哪一个函数,一定会陷入无穷无尽的循环调用中。