前言
在谈二阶构造模式之前,我们需要先学会灵活使用C++类中的静态成员函数,一般我们将其配合静态成员变量一起使用,用途最多用在统计该类创建的对象个数,除此之外,很多程序员在工作当中不会使用静态成员函数,今天要用的二阶构造模式与此密切相关!
什么是二阶构造模式?
二阶构造,顾名思义,那不就是分两个步骤完成构造函数嘛?嗯…,就是这个意思!
为什么要使用二阶构造模式?
问得好,首先我们要知道类的构造函数是为我们初始化类中的变量的,但他并不能保证对象构造成功。构造函数能决定对象的初始化状态,但决定不了对象的诞生,产生的半成品对象往往是bug的来源,因此我们必须要把bug扼杀在摇篮里。
第一阶:
初始化与资源无关的操作,该阶段不可能出现异常!
第二阶:
当构造函数中需要申请系统资源时(如操作文件、申请内存)都有可能会出现异常情况,若我们创建的类需要申请这些资源,那么一定要放在这个阶段来申请!
举例
首先看一下不适用二阶构造模式的例子,为了方便,我将类中函数的实现直接写在头文件里了
class TestClass
{
private:
int *point;
int size;
public:
TestClass(int size)
{
point = new int[size];
this->size = size;
}
};
在创建TestClass对象时,无论构造函数中申请内存成功与否,对象都产生了,万一申请内存失败,那么生成的这个对象就存在安全隐患,你去使用未初始化成功的point指针去访问数组,极有可能出现段错误。
HArray.h头文件
class HArray
{
private:
int *point;
int limit;
HArray();
HArray(int size);
bool Construct(int size);
public:
int size();
bool setvalue(int offset,int value);
bool getvalue(int offset,int *value);
static HArray* NewHArry(int size);
};
在HArray这个类中,可以发现我将构造函数的属性定义为private,那就是说我要生成HArray类的对象只能在该类中使用函数生成,没错,这个函数就是最下面的静态成员函数,接下来看HArray.c文件
HArray::HArray(int size)
{
limit = size;
}
bool HArray::Construct(int size)
{
point = new int[size];
if(!point)
return false;
return true;
}
HArray *HArray::NewHArry(int size)
{
HArray *ret = new HArray(size);
if(ret && ret->Construct(size))
return ret;
else
{
delete ret;
return NULL;
}
}
在HArray类的构造函数中,初始化limit初值,即为申请int型数组的长度,此为第一阶构造,绝对安全,不会有异常风险。
将申请内存的操作放在在Construct函数中执行,此为第二阶构造
NewHArray函数中我们自己先申请一个HArray类对象,若申请内存成功,则返回该对象的地址,否则就销毁刚刚申请的类对象,并返回空指针。
如此,当我们需要创建HArray对象时,使用如下方式即可,通过调用二阶构造函数,完成类对象的申请和初始化,若对象创建成功,则我们直接通过指针来操作这个对象,程序员自己不用再自己手动自己创建对象,只需要调用该类的二阶构造函数即可
int main(int argc, char *argv[])
{
HArray *h = HArray::NewHArry(100);
return 0;
}