二阶构造模式

模式:方法。设计模式,就是设计方法。前人证明了的行之有效的方法。

构造函数:

1.关于构造函数

 -类的构造函数用于对象的初始化。

 -构造函数与类同名并且没有返回值。

 -构造函数在对象定义时自动被调用。

问题:

1.如何判断构造函数的执行结果?

2.在构造函数中执行return语句会发生什么?

3.构造函数执行结束是否意味对象构造成功?

编程实验:异常的构造函数.cpp

 1 #include <stdio.h>
 2 
 3 class Test
 4 {
 5     int mi;
 6     int mj;
 7     bool mStatus;
 8 public:
 9     Test(int i, int j) : mStatus(false)
10     {
11         mi = i;
12         
13         return;
14         
15         mj = j;
16         
17         mStatus = true;
18     }
19     int getI()
20     {
21         return mi;
22     }
23     int getJ()
24     {
25         return mj;
26     }
27     int status()
28     {
29         return mStatus;
30     }
31 };
32 
33 int main()
34 {  
35     Test t1(1, 2);
36     
37     if( t1.status() )
38     {
39         printf("t1.mi = %d
", t1.getI());
40         printf("t1.mj = %d
", t1.getJ());
41     
42     }
43     
44     return 0;
45 }

你需要知道的真相:

-构造函数

1.只提供自动初始化变量的机会;

2.不能保证初始化逻辑一定成功;

3.执行return 语句后构造函数立即结束。

构造函数能决定的只是对象的初始状态,而不是对象的诞生。

半成品对象:

-初始化操作不能按照预期完成而得到的对象;

-半成品对象是合法的C++对象,也是BUG的重要来源。

半成品对象的危害

IntArray.cpp

 1 #include "IntArray.h"
 2 
 3 IntArray::IntArray(int len)
 4 {
 5     m_length = len;
 6 }
 7 
 8 bool IntArray::construct()
 9 {
10     bool ret = true;
11     
12     m_pointer = new int[m_length];
13     
14     if( m_pointer )
15     {
16         for(int i=0; i<m_length; i++)
17         {
18             m_pointer[i] = 0;
19         }
20     }
21     else
22     {
23         ret = false;
24     }
25     
26     return ret;
27 }
28 
29 IntArray* IntArray::NewInstance(int length) 
30 {
31     IntArray* ret = new IntArray(length);
32     
33     if( !(ret && ret->construct()) ) 
34     {
35         delete ret;
36         ret = 0;
37     }
38         
39     return ret;
40 }
41 
42 int IntArray::length()
43 {
44     return m_length;
45 }
46 
47 bool IntArray::get(int index, int& value)
48 {
49     bool ret = (0 <= index) && (index < length());
50     
51     if( ret )
52     {
53         value = m_pointer[index];
54     }
55     
56     return ret;
57 }
58 
59 bool IntArray::set(int index, int value)
60 {
61     bool ret = (0 <= index) && (index < length());
62     
63     if( ret )
64     {
65         m_pointer[index] = value;
66     }
67     
68     return ret;
69 }
70 
71 IntArray::~IntArray()
72 {
73     delete[]m_pointer;
74 }

针对上面的问题,我们如何使用一个行之有效的办法解决?

二阶构造:

-工程开发中的构造函数过程可分为

1.资源无关的初始化操作

  -不可能出现异常情况的操作

2.需要使用系统资源的操作

  -可能出现异常情况,如:内存申请,访问文件。

步骤:

创建对象——》资源无关初始操作——》资源相关初始操作——》资源申请成功——》true——》返回对象

代码:

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

小结:

-构造函数只能决定对象的初始化状态;

-构造函数中初始化操作的失败不影响对象的产生;

-初始化不完全的半成品对象是Bug的重要来源;

-二阶构造人为的将初始化过程分为两部分;

-二阶构造能够确保创建的对象都是完整初始化的。

原文地址:https://www.cnblogs.com/lemaden/p/10117583.html