C++的二阶构造模式
首先明白构造函数是什么:
- 类的构造函数用来对象的初始化
- 构造函数与类同名并且没有返回值
- 构造函数的在创建对象时候自动被调用
先抛出问题:
构造函数执行结果是什么?
构造函数中加上return会发生什么?
构造函数的执行结束是否意味着对象构造成功?
先上代码:
#include <stdio.h>
class Test
{
int mi;
int mj;
public:
Test(int i, int j)
{
mi = i;
mj = j;
}
int getI()
{
return mi;
}
int getJ()
{
return mj;
}
};
int main()
{
Test t1(1, 2);
printf("t1.mi = %d\n", t1.getI());
printf("t1.mj = %d\n", t1.getJ());
return 0;
}
上述的代码为简单的C++代码。结果是
t1.mi = 1
t1.mj = 2
对于上述的问题,我们要加一个return语句会发生什么?
#include <stdio.h>
class Test
{
int mi;
int mj;
public:
Test(int i, int j)
{
mi = i;
return;
mj = j;
}
int getI()
{
return mi;
}
int getJ()
{
return mj;
}
};
int main()
{
Test t1(1, 2);
printf("t1.mi = %d\n", t1.getI());
printf("t1.mj = %d\n", t1.getJ());
return 0;
}
结果:
t1.mi = 1
t1.mj = 2527220
mj的结果不是2.表明构造函数执行在return这个函数就结束了。
因此构造函数只能决定对象的初始状态,而不是决定对象的诞生。
在加return之后,t1这个对象并没有完全构造,所以是不可以正常使用的。因此他叫半成品对象。
半成品对象的概念:
初始化操作不能按照预期完成二得到的对象
半成品对象是合法的C++对象,但是同时它也是Bug的重要来源
一般企业中最难以调试的Bug,一是野指针(后面文章会写),其次就是这个半成品对象带来的Bug。 为了避免这样的结果,我们要引出二阶构造的含义。
工程开发中的构造过程可分为
资源无关的初始化操作(即不可能出现异常情况的操作)肯定不会出错的情况
需要使用系统资源的操作(即可能出现异常情况,如:内存申请,访问文件)怀疑出错的
他的大致流程如下:
先看一下代码:
#include <stdio.h>
class TwoPhaseCons
{
private:
TwoPhaseCons() // 第一阶段构造函数
{
}
bool construct() // 第二阶段构造函数
{
return true;
}
public:
static TwoPhaseCons* NewInstance(); // 对象创建函数
};
TwoPhaseCons* TwoPhaseCons::NewInstance()
{
TwoPhaseCons* ret = new TwoPhaseCons();
// 若第二阶段构造失败,返回 NULL
if( !(ret && ret->construct()) )
{
delete ret;
ret = NULL;
}
return ret;
}
int main()
{
TwoPhaseCons* obj = TwoPhaseCons::NewInstance();
printf("obj = %p\n", obj);
delete obj;
return 0;
}
第一阶段的构造函数与第二阶段的构造函数放在private里面,外部无法调用
但是在public中,定义的static TwoPhaseCons* NewInstance(); 返回的是TwoPhaseCons型的对象.那么通过可以调用构造函数的private。因为处于NewInstance内部,所以它可以调用构造函数。
TwoPhaseCons* ret = new TwoPhaseCons();
在main函数中有一句话:TwoPhaseCons* obj = TwoPhaseCons::NewInstance();这是调用NewInstance()函数创建obj 对象,因为构造函数TwoPhaseCons为private类型,所以想创建对象,必须用public中的静态创建函数:static TwoPhaseCons* NewInstance();
**
总结:
构造函数只能决定对象的初始化状态
构造函数中初始化操作的失败不影响对象的诞生
初始化不完全的半成品对象是Bug的主要来源
二阶构造人为的将初始化过程分成两部分 二阶构造能够确保创建的对象都是完整初始化的
**