zoukankan      html  css  js  c++  java
  • 第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
    ", t1.getI(), t1.getJ());
    33     printf("t2.i = %d, t2.j = %d
    ", 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
    ", 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     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
    ", 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     
    35     a.free();
    36     b.free();
    37     
    38     return 0;
    39 }

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

    运行结果如下:

     小结:

  • 相关阅读:
    TFS 2013”无法移除仍为团队管理员身份的标识”
    如何在TFS的过程模板中添加报表
    集成TFS Build生成与SonarQube获取代码分析结果
    TFS 2015 Update 2功能探索
    使用Azure Automation(自动化)定时关闭和启动虚拟机
    TFS 与活动目录AD(Active Directory)的同步机制
    Eclipse 常用快捷键
    JMeter网站并发性测试
    docker安装配置GitLab
    javaWeb项目在用maven启动时必须要用到的坐标
  • 原文地址:https://www.cnblogs.com/wanmeishenghuo/p/9568837.html
Copyright © 2011-2022 走看看