您的位置:首页 > 编程语言 > C语言/C++

C++学习笔记--二阶构造模式

2017-11-26 19:29 375 查看
如何判断构造函数的执行结果?在构造函数中执行return语句会发生什么?构造函数执行结束是否意味着对象构造成功?

在一般的构造函数中我们确实无法判断构造函数的执行结果,当我们在函数里添加bool标志虽然可以通过检测返回值但是终究不是一个好方法;在构造函数里如果添加了return语句的话,当执行到return语句时就会立即返回,如果是在初始化完成前返回的话就会产生一个半成品对象,即初始化操作不能按照预期完成而得到的对象,它是合法的,但不是我们需要的,这也是bug的一个重要来源。

class Test
{
...
...
int status()
{
return mStatus;
}

Test(int i, int j) : mStatus(false)
{
mi = i;

return;

mj = j;

mStatus = true;
}

...
...
...

}
int main()
{
Test t1(1, 2);

if( t1.status() )
{
printf("t1.mi = %d\n", t1.getI());
printf("t1.mj = %d\n", t1.getJ());
}
return 0;
}


当定义对象时就会调用构造函数,构造函数体里有return语句,结果就会导致对象没有完全初始化就返回了,所以对象初始化状态为false,main中什么都无法打印出来。虽然能说明对象是存在问题的,是一个半成品对象,但是它依然可以使用,说明这种实现并不完美。构造函数只提供了一个自动初始化对象的机会,不能保证初始化结果一定成功,所以,构造函数只能决定对象的初始状态而不能决定对象的产生。

所以我们需要进行改善了,通常使用的是二阶构造,它将构造过程分为两部分,与资源无关的初始化操作和需要使用系统资源的操作,第一部分由于只是进行一些赋值操作那肯定就不可能出现异常情况的操作,第二部分由于进行内存分配或文件访问可能会出现异常情况。其具体流程如下图:



具体实现可以将C++自身的构造函数作为第一阶段的实现用来调用一些简单的赋值操作,第二阶段就是一个普通的成员函数,将所有可能引起失败的操作全部放在里面,失败返回false,成功返回true,当两个阶段都成功时就能得到一个合法可用健康的C++对象。那么这个采用二阶构造的类就应该形如下面这样:

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;
}
首先就是调用构造函数动态创建一个堆空间的类对象,同时完成第一阶段的操作,接着进行第二阶段的判断,要是成功就返回类对象的地址,失败返回NULL。

TwoPhaseCons* obj = TwoPhaseCons::NewInstance();
这就是创建一个新式类对象的方式。二阶构造的意义就在于获得的要么是一个合法有效的对象,要么返回就是空,杜绝了半成品对象。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: