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

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/qq_22847457/article/details/96479327

1.构造函数的回顾

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

2.面试题

  • 1. 如何判断构造函数的执行结果?
    • 没有办法直接判断构造函数的执行结果。 
  •  2. 在构造函数中执行return语句会发生什么? 
    • return语句执行后,构造函数立即返回(return前面初始化成功,后面为随机值)。
  • 3. 构造函数执行结束是否意味着对象构造成功?
    • 构造函数执行结束,且并不意味着对象构造成功。

 
 
  1. #include<stdio.h>
  2. class Test
  3. {
  4. int mi;
  5. int mj;
  6. bool mStatus;
  7. public:
  8. Test( int i, int j) :mStatus( false)
  9. {
  10. mi = i;
  11. return;
  12. mj = j;
  13. mStatus = true;
  14. }
  15. int getI()
  16. {
  17. return mi;
  18. }
  19. int getJ()
  20. {
  21. return mj;
  22. }
  23. int status()
  24. {
  25. return mStatus;
  26. }
  27. };
  28. int main()
  29. {
  30. Test t1(1, 2);
  31. if (t1.status())
  32. {
  33. printf( "t1.mi = %d\n", t1.getI());
  34. printf( "t1.mi = %d\n", t1.getJ());
  35. }
  36. getchar();
  37. return 0;
  38. }
  • 打印结果为空,说明main函数中if判断为false。说明构造函数包含return之后会中止执行。

3.你该知道的真相

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

4.半成品对象的概念 

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

5.构造中的异常

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

 
 
  1. #include <iostream>
  2. using namespace std;
  3. class Test
  4. {
  5. public:
  6. Test()
  7. {
  8. cout << "Test()" << endl;
  9. throw 0;
  10. }
  11. virtual ~Test()
  12. {
  13. cout << "~Test()" << endl;
  14. }
  15. };
  16. int main(int argc, char *argv[])
  17. {
  18. Test *p = reinterpret_cast<Test*>( 1);
  19. try
  20. {
  21. p = new Test();
  22. }
  23. catch (...)
  24. {
  25. cout << "Exception..." << endl;
  26. }
  27. cout << "p=" << p << endl;
  28. getchar();
  29. return 0;
  30. }
  • 运行结果:

6.析构中的异常

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

7.二阶构造 

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

  • 二阶构造示例—

 
 
  1. class TwoPhaseCons
  2. {
  3. private:
  4. TwoPhaseCons()
  5. {
  6. //第一阶段构造函数,资源无关操作
  7. }
  8. bool construct()
  9. {
  10. //第二阶段构造函数,使用系统资源操作
  11. return true;
  12. }
  13. public:
  14. static TwoPhaseCons* New工nstance () ; //对象创建函数
  15. } ;
  •  二阶构造示例 

 
 
  1. TwoPhaseCons* TwoPhaseCons::NewInstance()
  2. {
  3. TwoPhaseCons* ret = new TwoPhaseCons();
  4. //若第二阶段构造失败,返回NULL
  5. if(! (ret && ret->construct()))
  6. {
  7. delete ret;
  8. ret = NULL;
  9. }
  10. return ret;
  11. }

8.编程实例


 
 
  1. #include<stdio.h>
  2. class TwoPhaseCons
  3. {
  4. private:
  5. TwoPhaseCons()
  6. {
  7. }
  8. bool construct()
  9. {
  10. return true;
  11. }
  12. public:
  13. static TwoPhaseCons* NewInstance(); // 对象创建函数
  14. };
  15. TwoPhaseCons* TwoPhaseCons::NewInstance()
  16. {
  17. TwoPhaseCons *ret = new TwoPhaseCons();
  18. //若第二阶段构造失败,返回NULL
  19. if (!(ret && ret->construct()))
  20. {
  21. delete ret;
  22. ret = NULL;
  23. }
  24. return ret;
  25. }
  26. int main()
  27. {
  28. TwoPhaseCons *obj = TwoPhaseCons::NewInstance();
  29. printf( "obj = %p\n", obj);
  30. delete obj;
  31. getchar();
  32. return 0;
  33. }
  • 打印结果为任意地址

9.小结

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值