C++深度解析(17)—二阶构造模式

本文探讨了构造函数在对象初始化中的作用与限制,包括构造函数的执行结果判断、执行流程中断的影响、异常处理策略及二阶构造模式的应用。强调了构造函数并不能保证对象的成功创建,半成品对象可能导致的问题及解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.构造函数的回顾

  • 类的构造函数用于对象的初始化 
  • 构造函数与类同名并且没有返回值 
  • 构造函数在对象定义时自动被调用

2.面试题

  • 1. 如何判断构造函数的执行结果?
    • 没有办法直接判断构造函数的执行结果。 
  •  2. 在构造函数中执行return语句会发生什么? 
    • return语句执行后,构造函数立即返回(return前面初始化成功,后面为随机值)。
  • 3. 构造函数执行结束是否意味着对象构造成功?
    • 构造函数执行结束,且并不意味着对象构造成功。
#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.mi = %d\n", t1.getJ());
	}
	
	getchar();
	
	return 0;
}
  • 打印结果为空,说明main函数中if判断为false。说明构造函数包含return之后会中止执行。

3.你该知道的真相

  • 构造函数 
    • 只提供自动初始化成员变量的机会 
    • 不能保证初始化逻辑—定成功 
    • 执行return语句后构造函数立即结束
  • 真相的意义:构造函数能决定的只是对象的初始状态,而不是对象的诞生!!

4.半成品对象的概念 

  • 初始化操作不能按照预期完成而得到的对象,半成品对象是合法的C++对象,也是Bug的重要来源

5.构造中的异常

  • 如果构造函数中抛出异常会发生什么情况?
    • 构造过程立即停止
    • 当前对象无法生成
    • 析构函数不会被调用
    • 对象所占用的空间立即收回
  • 工程项目中的建议 
    • 不要在构造函数中抛出异常 
    • 当构造函数可能产生异常时,使用二阶构造模式 
#include <iostream>

using  namespace  std;

class  Test 
{
public:
	Test()
	{
		cout << "Test()" << endl;

		throw  0;
	}
	
	virtual ~Test()
	{
		cout << "~Test()" << endl;
	}
};

int main(int  argc, char  *argv[])
{
	Test *p = reinterpret_cast<Test*>(1);

	try 
	{
		p  = new Test();
	}
	
	catch (...)
	{
		cout  << "Exception..." << endl;
	}

	cout  << "p=" << p  << endl;

	getchar();
	
	return  0;
}
  • 运行结果:

6.析构中的异常

  • 避免在析构函数中抛出异常!! 
  • 析构函数的异常将导致: 对象所使用的资源无法完全释放。

7.二阶构造 

  • 工程开发中的构造过程可分为 
    • 资源无关的初始化操作 :不可能出现异常情况的操作 
    • 需要使用系统资源的操作 :可能出现异常情况,如:内存申请,访问文件

  • 二阶构造示例—
class TwoPhaseCons  
{   
private:   
    TwoPhaseCons()   
    {  
        //第一阶段构造函数,资源无关操作   
    }   
  
    bool construct()   
    {  
        //第二阶段构造函数,使用系统资源操作   
        return true;   
    }   
public:   
    static TwoPhaseCons* New工nstance () ; //对象创建函数   
} ;   
  •  二阶构造示例 
TwoPhaseCons* TwoPhaseCons::NewInstance()   
{   
    TwoPhaseCons* ret = new TwoPhaseCons();   
       
    //若第二阶段构造失败,返回NULL  
    if(! (ret && ret->construct()))   
    {   
        delete ret;   
        ret = NULL;   
    }   
  
    return ret;   
}  

8.编程实例

#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\n", obj);
	
	delete obj;

	getchar();
	
	return 0;
}
  • 打印结果为任意地址

9.小结

  • 构造函数只能决定对象的初始化状态 
  • 构造函数中初始化操作的失败不影响对象的诞生 
  • 初始化不完全的半成品对象是Bug的重要来源
  • 二阶构造人为的将初始化过程分为两部分 
  • 二阶构造能够确保创建的对象都是完整初始化的
  • 构造函数和析构函数中不要抛出异常
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值