回顾
*类的构造函数用于对象的初始化
*构造函数与类同名并且没有返回值
*构造函数在对象定义时自动被调用
问题
1.如何判断构造函数的执行结果?无法判断
2.在构造函数中执行return语句会发生什么?结束构造函数
3.构造函数执行结束是否意味着对象构造成功?否
构造函数的执行结束,对象可能只是个半成品,有可能遭遇return或者系统资源申请不成功。
解决方案一:在构造函数末尾设置标志位,但是不太美观
#include <stdio.h>
class Test
{
int mi;
int mj;
bool mStatus;
public:
Test(int i, int j) : mStatus(false)
{
mi = i;
return;
mj = j;
mStatus = true;
}
int getI()
{
return mi;
}
int getJ()
{
return mj;
}
int status()
{
return mStatus;
}
};
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语句后构造函数立即结束
构造函数能决定的只是对象的初始状态,而不是对象的诞生
*半成品对象的概念
——初始化操作不能按照预期完成而得到的对象
——半成品对象是合法的C++对象,也是Bug的重要来源
二阶构造
*构造过程可分为
资源无关的初始化操作(不可能出现异常情况)
需要使用系统资源的操作(可能出现异常情况,如:内存申请,访问文件)
下面是流程图和示例程序
下面我们来体会一下
#include <stdio.h>
class TwoPhaseCons
{
private:
TwoPhaseCons()
{
}
bool construct(){
return true;
}
public:
static TwoPhaseCons* NewInstance();
};
TwoPhaseCons* TwoPhaseCons::NewInstance()
{
TwoPhaseCons* ret = new TwoPhaseCons();
if(!(ret && ret->construct())){
delete ret;
ret = NULL;
}
return ret;
}
int main()
{
TwoPhaseCons* obj = TwoPhaseCons::NewInstance();
printf("obj = %p\n", obj);
return 0;
}
如果直接调用构造函数的话显然不行,构造函数是私有的,只通过
TwoPhaseCons::NewInstance()创建对象
有些同学提出疑问了,这样子的话,那对象就不能放进栈空间中了。
在实际工程中,对象往往是非常巨大的,所以更应该放在堆空间中。
小结
*构造函数只能决定对象的初始化状态
*构造函数中初始化操作的失败不影响对象的诞生
*初始化不完全的半成品是Bug的重要来源
*二阶构造人为的将初始化过程分为两部分
*二阶构造能够确保创建对象都是完整初始化的
qq:335366243
微信:zhong_335366243