第19课 对象的构造(下)

特殊的构造函数:

示例如下:

 1 #include <stdio.h>
 2 
 3 class Test
 4 {
 5 private:
 6     int i;
 7     int j;
 8 public:
 9     int getI()
10     {
11         return i;
12     }
13     int getJ()
14     {
15         return j;
16     }
17     /*Test(const Test& t)
18     {
19         i = t.i;
20         j = t.j;
21     }
22     Test()
23     {
24     }*/
25 };
26 
27 int main()
28 {
29     Test t1;
30     Test t2 = t1;
31     
32     printf("t1.i = %d, t1.j = %d\n", t1.getI(), t1.getJ());
33     printf("t2.i = %d, t2.j = %d\n", t2.getI(), t2.getJ());
34     
35     return 0;
36 }

17-24行就是编译器替我们提供的默认构造函数和拷贝构造函数。

运行结果如下:

 可以看到t1和t2中i和j的值是一样的。

当我们的类中没有编写任何的构造函数时,编译器才会给我们提供默认的构造函数,拷贝构造函数是构造函数的一种。

拷贝构造函数:

兼容C语言的方式类似于 Test t1 = t2这种初始化方式,就是用一个已存在的对象t2来初始化t1,这时候就会调用拷贝构造函数。

拷贝构造函数的玄机:

对象的初始化实验:

我们可以看到t1和t2对象中的p指向同一个内存地址。

 我们在构造函数中申请了内存,就应该释放,两个对象我们需要释放两次,因为两个对象的p指向同一个内存空间,释放两次就会发生错误。

因此,我们需要手工提供拷贝构造函数进行深拷贝。

如下:

 1 #include <stdio.h>
 2 
 3 class Test
 4 {
 5 private:
 6     int i;
 7     int j;
 8     int* p;
 9 public:
10     int getI()
11     {
12         return i;
13     }
14     int getJ()
15     {
16         return j;
17     }
18     int* getP()
19     {
20         return p;
21     }
22     Test(const Test& t)
23     {
24         i = t.i;
25         j = t.j;
26         p = new int;
27         
28         *p = *t.p;
29     }
30     Test(int v)
31     {
32         i = 1;
33         j = 2;
34         p = new int;
35         
36         *p = v;
37     }
38     void free()
39     {
40         delete p;
41     }
42 };
43 
44 int main()
45 {
46     Test t1(3);
47     Test t2(t1);
48     
49     printf("t1.i = %d, t1.j = %d, *t1.p = %d\n", t1.getI(), t1.getJ(), *t1.getP());
50     printf("t2.i = %d, t2.j = %d, *t2.p = %d\n", t2.getI(), t2.getJ(), *t2.getP());
51     
52     t1.free();
53     t2.free();
54     
55     return 0;
56 }

 22行的拷贝构造函数进行可深拷贝。第47行的初始化就会调用这个拷贝构造函数,我们也可以写成Test t2 = t1,意义是一样的,都会调用拷贝构造函数。

运行结果如下:

 t1和t2中的p指向的地址不一样,这称为它们的物理状态不一样,但是p指向的内存单元中的值是一样的,这称为逻辑状态相同。

深拷贝:

问题分析:这就是上面浅拷贝时程序崩溃的原因

一般性原则:

自定义拷贝构造函数时,必然需要实现深拷贝,要不然没有必要自定义拷贝构造函数。

数组类的改进:

 1 #ifndef _INTARRAY_H_
 2 #define _INTARRAY_H_
 3 
 4 class IntArray
 5 {
 6 private:
 7     int m_length;
 8     int* m_pointer;
 9 public:
10     IntArray(int len);
11     IntArray(const IntArray& obj);
12     int length();
13     bool get(int index, int& value);
14     bool set(int index ,int value);
15     void free();
16 };
17 
18 #endif
 1 #include "IntArray.h"
 2 
 3 IntArray::IntArray(int len)
 4 {
 5     m_pointer = new int[len];
 6     
 7     for(int i=0; i<len; i++)
 8     {
 9         m_pointer[i] = 0;
10     }
11     
12     m_length = len;
13 }
14 
15 IntArray::IntArray(const IntArray& obj)
16 {
17     m_length = obj.m_length;
18     
19     m_pointer = new int[obj.m_length];
20     
21     for(int i=0; i<obj.m_length; i++)
22     {
23         m_pointer[i] = obj.m_pointer[i];
24     }
25 }
26 
27 int IntArray::length()
28 {
29     return m_length;
30 }
31 
32 bool IntArray::get(int index, int& value)
33 {
34     bool ret = (0 <= index) && (index < length());
35     
36     if( ret )
37     {
38         value = m_pointer[index];
39     }
40     
41     return ret;
42 }
43 
44 bool IntArray::set(int index, int value)
45 {
46     bool ret = (0 <= index) && (index < length());
47     
48     if( ret )
49     {
50         m_pointer[index] = value;
51     }
52     
53     return ret;
54 }
55 
56 void IntArray::free()
57 {
58     delete[]m_pointer;
59 }

主程序如下:

 1 #include <stdio.h>
 2 #include "IntArray.h"
 3 
 4 int main()
 5 {
 6     IntArray a(5);    
 7     
 8     for(int i=0; i<a.length(); i++)
 9     {
10         a.set(i, i + 1);
11     }
12     
13     for(int i=0; i<a.length(); i++)
14     {
15         int value = 0;
16         
17         if( a.get(i, value) )
18         {
19             printf("a[%d] = %d\n", i, value);
20         }
21     }
22     
23     IntArray b = a;
24     
25     for(int i=0; i<b.length(); i++)
26     {
27         int value = 0;
28         
29         if( b.get(i, value) )
30         {
31             printf("b[%d] = %d\n", i, value);
32         }
33     }
34     
35     a.free();
36     b.free();
37     
38     return 0;
39 }

上述程序中我们增加了拷贝构造函数,实现了深拷贝。

运行结果如下:

 小结:

猜你喜欢

转载自www.cnblogs.com/wanmeishenghuo/p/9568837.html