【C++】C++的二阶构造模式(避免构造bug)

来源

https://blog.csdn.net/qq_37375427/article/details/78797953

C++bug来源

  1. 野指针
  2. 对象构造未成功(在构造函数中出现了异常)

构造函数

  1. 只提供自动初始化成员变量的机会
  2. 不能保证初始化逻辑一定成功
  3. 执行return语句后构造函数立即结束

结论:
构造函数能决定的只是对象的初始状态,而不是对象的诞生!!!,会出现半成品对象

半成品对象

半成品对象的概念:

  • 初始化操作不能按照预期完成二得到的对象
  • 半成品对象是合法的C++对象,但是同时它也是Bug的重要来源
    一般企业中最难以调试的Bug,一是野指针(后面文章会写),其次就是这个半成品对象带来的Bug。

利用二阶构造解决

那么我们该如何避免这样的Bug呢?下面就引出二阶构造的含义:
工程开发中的构造过程可分为:

  1. 不可能出现异常情况的操作
    资源无关的初始化操作
  2. 需要使用系统资源的操作
    可能出现异常情况,如:内存申请,访问文件

二阶构造大体流程:
在这里插入图片描述

代码示例

#include <iostream>
using namespace std;
class TwoPhaseCons
{
public:
	static TwoPhaseCons* NewInstance();//对象构造函数:整合第一第二阶段构造函数
private:
	TwoPhaseCons(){}//第一阶段构造函数
	bool construct() { return true; }//第二阶段构造函数
};

int main()
{
	TwoPhaseCons* obj = TwoPhaseCons::NewInstance();
	cout << "obj=" << obj << endl;
	delete obj;
	return 0;
}

TwoPhaseCons * TwoPhaseCons::NewInstance()
{
	TwoPhaseCons* ret = new TwoPhaseCons();

	//分配内存失败或者第二阶段构造函数失败
	if (!(ret && ret->construct()))
	{
		delete ret;
		ret = nullptr;
	}
	return ret;
}

运行结果:
obj=012C7460

说明

第一阶段构造函数与第二阶段构造函数放到private里面了,外部无法调用。
但是在public中,定义的是static 型的NewInstance函数,返回TwoPhaseCons类型的对象,那么通过它就可以调用private里面的构造函数。例如在NewInstance函数里可以有如下代码: TwoPhaseCons* ret = new TwoPhaseCons();,因为处于NewInstance内部,所以它可以调用构造函数。

同时我们也可以看出,用了二阶构造模式后,对象只能在堆空间上进行构造而不能在栈空间上构造这样好么?答案是肯定的,因为工程上的对象往往是巨大的,一般都会放到堆空间上进行构造。

总结

  • 构造函数只能决定对象的初始化状态
  • 构造函数中初始化操作的失败不影响对象的诞生
  • 初始化不完全的半成品对象是Bug的主要来源
  • 二阶构造人为的将初始化过程分成两部分
  • 二阶构造能够确保创建的对象都是完整初始化的

猜你喜欢

转载自blog.csdn.net/vict_wang/article/details/88751771