第19课

第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
", t1.getI(), t1.getJ());
39     printf("t2.i = %d, t2.j = %d
", 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
", t1.getI(), t1.getJ(), *t1.getP());
50     printf("t2.i = %d, t2.j = %d, *t2.p = %d
", 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
", 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
", i, value);
32         }
33     }
34     return 0;
35 }
main.cpp

3. 小结

  (1)C++ 编译器会默认提供构造函数

  (2)无参构造函数用于定义对象的默认初始状态

  (3)拷贝构造函数在创建对象时拷贝对象的状态

  (4)对象的拷贝有浅拷贝深拷贝两种方式。浅拷贝使得对象的物理状态相同;深拷贝使得对象的逻辑状态相同。

    

原文地址:https://www.cnblogs.com/shiwenjie/p/7231721.html