首先,我们来看一下下面例子:
class Base{
public:
Base() {
Base(0);
cout<<"Default constructor."<<endl;
cout<<"i = "<<i<<endl;
}
Base(int ii): i(ii) {
cout<<"Constructor."<<endl;
cout<<"i = "<<i<<endl;
}
int i;
};
int _tmain(int argc, _TCHAR* argv[])
{
Base *b = new Base();
cout<<b->i<<endl;
system("pause.");
return 0;
}
Constructor.
i = 0
Default constructor.
i = -842150451
-842150451
请按任意键继续. . .
出人意料地,i的值并不是0,而是一个乱七八糟的数字。
分析如下:
我们知道,当定义一个对象时,会按顺序做2件事情:
1)分配好内存(非静态数据成员是未初始化的)
2)调用构造函数(构造函数的本意就是初始化非静态数据成员)
显然上面代码中,Base *b = new Base();这里已经为b所指向的对象分配了内存,然后调用默认构造函数,但是默认构造函数还未执行完,却调用了另一个带参数构造函数,这样相当于产生了一个匿名的临时Base对象,它调用Base(int)构造函数,将这个匿名临时对象自己的数据成员 i 初始化为0;但是 b 所指向的的数据成员并没有得到初始化。于是d->i 是未初始化的,因此其值也是不确定的
从这里,我们归纳如下:
1)在c++里,由于构造函数允许有默认参数,使得这种构造函数调用构造函数来重用代码的需求大为减少。
2)如果仅仅为了一个构造函数重用另一个构造函数的代码,那么完全可以把构造函数中的公共部分抽取出来定义一个成员函数(推荐为private),然后在每个需要这个代码的构造函数中调用该函数即可。
3)尽量不要在构造函数中调用构造函数。