第19课 - 对象的构造(下)
1. 特殊的构造函数
(1)无参构造函数
当类中没有定义构造函数时,编译器默认提供一个无参构造函数,并且其函数体为空。
(2)拷贝构造函数
当类中没有定义拷贝构造函数时,编译器默认提供一个拷贝构造函数,简单的进行成员变量的值复制。
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
18 Test(const Test& t)
19 {
20 i = t.i;
21 j = t.j;
22 }
23
24 /*
25 Test()
26 {
27 }
28 */
29 };
30
31 int main()
32 {
33 Test t1;
34
35 /*
36 Test t2 = t1;
37
38 printf("t1.i = %d, t1.j = %d\n", t1.getI(), t1.getJ());
39 printf("t2.i = %d, t2.j = %d\n", t2.getI(), t2.getJ());
40 */
41
42 return 0;
43 }
特殊的构造函数
2. 拷贝构造函数
2.1 拷贝构造函数的意义
(1)兼容 C 语言的初始化方式 int i = 1; int j = i;
(2)初始化行为能够符合预期的逻辑
(3)深拷贝和浅拷贝
① 浅拷贝:拷贝后对象的物理状态相同 【编译器提供的拷贝构造函数只提供浅拷贝】
② 深拷贝:拷贝后对象的逻辑状态相同
1 #include <stdio.h>
2
3 class Test
4 {
5 private:
6 int i;
7 int j;
8 int* p;
9
10 public:
11 int getI(){return i;}
12
13 int getJ(){return j;}
14
15 int* getP(){return p;}
16
17 /*
18 //拷贝构造函数
19 Test(const Test& t)
20 {
21 i = t.i;
22 j = t.j;
23 p = new int;
24
25 *p = *t.p;
26 }
27 */
28
29
30 //带参构造函数
31 Test(int v)
32 {
33 i = 1;
34 j = 2;
35 p = new int;
36
37 *p = v;
38 }
39
40 ~Test(){delete p;}
41
42 };
43
44 int main()
45 {
46 Test t1(3); //调用Test(int v);
47 Test t2(t1); //调用Test(const Test& t)
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 return 0;
53 }
对象的初始化
2.2 什么时候需要进行深拷贝?
(1)对象中有成员指向了系统中的资源
- 成员指向了动态内存空间
- 成员打开了外存中的文件
- 成员使用了系统中的网络端口
- ......
(2)问题分析
★★★一般性原则:自定义拷贝构造函数的时候,必须思考这个拷贝函数是否需要实现深拷贝? 如果不需要,为什么不使用编译器提供的拷贝构造函数?
【编程实验】数组类的改进
1 #ifndef _INTARRAY_H_
2 #define _INTARRAY_H_
3
4 class IntArray
5 {
6 private:
7 int m_length;
8 int* m_pointer;
9
10 public:
11 IntArray(int len);
12 IntArray(const IntArray& obj);
13 ~IntArray();
14
15 int length();
16 bool get(int index, int& value);
17 bool set(int index, int value);
18 };
19
20 #endif
IntArray.h
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 IntArray::~IntArray()
28 {
29 if(m_pointer)
30 {
31 delete[] m_pointer;
32 }
33 }
34
35 int IntArray::length()
36 {
37 return m_length;
38 }
39
40 bool IntArray::get(int index, int& value)
41 {
42 bool bRet = (0 <= index) && (index <m_length);
43
44 if(bRet)
45 {
46 value = m_pointer[index];
47 }
48
49 return bRet;
50 }
51
52 bool IntArray::set(int index, int value)
53 {
54
55 bool bRet = (0 <= index) && (index <m_length);
56
57 if(bRet)
58 {
59 m_pointer[index] = value;
60 }
61
62 return bRet;
63 }
IntArray.cpp
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 return 0;
35 }
main.cpp
3. 小结
(1)C++ 编译器会默认提供构造函数
(2)无参构造函数用于定义对象的默认初始状态
(3)拷贝构造函数在创建对象时拷贝对象的状态
(4)对象的拷贝有浅拷贝和深拷贝两种方式。浅拷贝使得对象的物理状态相同;深拷贝使得对象的逻辑状态相同。