0x01 为什么需要使用二阶构造模式
- 在创建对象的时候无法判断构造函数的执行结果
- 以在构造函数中执行return语句时为例,这样的结果是对象会诞生但是初始化可能会存在问题
- 构造函数执行结束并不意味着对象构造成功,因为对象的初始化可能不是预期的,比如初始化过程有内存申请,访问文件等操作
如果初始化操作不能按照预期完成而得到的对象叫半成品对象,半成品对象是合法的C++对象,也是Bug的重要来源。
0x02 何时使用二阶构造
有需要使用系统资源的操作(可能出现异常的情况):
- 内存申请
- 访问文件
0x03 如何使用二阶构造
代码示例:
#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
", obj);
delete obj;
return 0;
}
二阶构造模式的使用:
-
将需要初始化的内容分为两个阶段:资源无关初始操作、系统资源申请操作。
-
构造函数、construct()都使用private进行封装,因此无法通过类来定义对象。
-
类中定义静态成员函NewInstance()数作为对象创建函数。static TwoPhaseCons* NewInstance();
-
在对象函数中使用new创建对象,TwoPhaseCons* ret = new TwoPhaseCons();
-
在对象创建函数中对new对象创建是否成功以及二阶段构造是否成功进行判断
TwoPhaseCons* TwoPhaseCons::NewInstance() { TwoPhaseCons* ret = new TwoPhaseCons(); // 若第二阶段构造失败,返回 NULL if( !(ret && ret->construct()) ) { delete ret; ret = NULL; } return ret; }