铅笔

在你的害怕中坚持的越多,你就会越自信
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

数组类的创建(下)

Posted on 2018-11-14 19:37  黑色の铅笔  阅读(256)  评论(0编辑  收藏  举报
创建StaticArray时,数组的大小必须是明确指定的,是一种限制。
全新的数组类:DynamicArray使用时其对象代表的数组的大小能够动态的指定
1、DynamicArray设计要点
  • 类模板
  • (任意时刻)动态确定内部数组空间大小  即存储数组的空间可以动态的指定
  • 实现函数返回数组长度
  • 拷贝构造和赋值操作
2、DynamicArray类的声明

 


3、DynamicArray实现
DynamicArray.h
 
  1 #ifndef DYNAMICARRAY_H
  2 #define DYNAMICARRAY_H
  3 #include "array.h"
  4 
  5 namespace   DataStructureLib
  6 {
  7 template <typename T>
  8 class DynamicArray:public Array<T>
  9 {
 10 protected:
 11     int m_length;
 12 public:
 13     DynamicArray(int length)
 14     {
 15         m_array=new T[length];
 16         if(m_array!=NULL)
 17         {
 18              m_length=length;
 19         }
 20        else
 21         {
 22             THROW_EXCEPTION(NotEnoughMemoryException,"No Enough Memory to Create DynamicArray...");
 23         }
 24     }
 25 
 26     DynamicArray(const DynamicArray<T>&  obj)
 27     {
 28         m_array=new T[obj.length()];
 29         if(m_array!=NULL)
 30         {
 31 
 32              for(int i=0;i<obj.length();i++)
 33              {
 34                   this->m_array[i]=obj.m_array[i];
 35              }
 36              m_length=obj.length();
 37         }
 38        else
 39         {
 40             THROW_EXCEPTION(NotEnoughMemoryException,"No Enough Memory to Create DynamicArray...");
 41         }
 42     }
 43 
 44     DynamicArray& operator =(DynamicArray & obj)
 45     {
 46         //delete m_array [];
 47         //这里不能先delete[] this->m_array,再
 48         //赋值,因为delete可能会引起T调用析构函数,而如果在析构函数中抛出异常,以下对
 49         //成员变量的赋值都将无法进行,从而造成函数异常时的不安全。因此,正确的顺序应该是
 50         //先对成员变量赋值,最后再释放m_array的旧空间。
 51 
 52          if(this!=&obj)
 53          {
 54              //1. 分配新内存
 55              T* array=new T[obj.length()];
 56              //2. 拷贝数组的
 57              for(int i=0;i<obj.length();i++)
 58              {
 59                  array[i]=obj[i];
 60              }
 61               //3. 设置变量
 62              T* temp=this->m_array;//先设置参数,再删除m_array,以确保异常安全
 63 
 64              this->m_length=obj.length();
 65              m_array=array;
 66 
 67              delete    []temp;
 68          }
 69 
 70         return *this;
 71     }
 72 
 73     int length() const
 74     {
 75         return m_length;
 76     }
 77 
 78     void resize(int length)
 79     {
 80         if(m_length!=length)
 81         {
 82             int size=(m_length<length)?m_length:length;
 83 
 84             T* array=new T[size];
 85 
 86             if(array!=NULL)
 87             {
 88                 for(int i=0;i<size;i++)
 89                 {
 90                     array[i]=m_array[i];
 91                 }
 92 
 93                 T* temp=m_array;
 94 
 95                 m_array=array;
 96                 m_length=length;
 97 
 98                 delete []temp;
 99             }
100             else
101             {
102                 THROW_EXCEPTION(NotEnoughMemoryException, "Not enough memory to resize Object ....");
103             }
104 
105 
106         }
107     }
108 
109     ~DynamicArray()
110     {
111         delete []m_array;
112     }
113 };
114 }
115 #endif // DYNAMICARRAY_H

 main.cpp

 1 #include <iostream>
 2 #include "Exception.h"
 3 #include "dynamicarray.h"
 4 
 5 using namespace std;
 6 using namespace DTLib;
 7 
 8 int main()
 9 {
10    DynamicArray<int> d(5);
11 
12    for(int i=0;i<d.length();i++)
13    {
14        d[i]=i*i;
15    }
16 
17 
18    for(int i=0;i<d.length();i++)
19    {
20        cout<<d[i]<<endl;
21    }
22 
23    d.resize(5);
24 
25    for(int i=0;i<d.length();i++)
26    {
27        cout<<d[i]<<endl;
28    }
29 
30     DynamicArray<int> d2(10);
31 
32     d2=d;
33 
34     for(int i=0;i<d2.length();i++)
35     {
36         cout<<d2[i]<<endl;
37     }
38 
39    return 0;
40 }

3. DynamicArray类的问题与重构

(1)逻辑问题:

  ①函数实现存在重复的逻辑(如赋值与resize函数)

  ②从逻辑看,代码可分解出更细的功能(如分配新内存、数组拷贝、设置新变量等)

(2)代码优化

  ①init():对象构造时的初始化操作

  ②copy():在堆空间中申请新的内存,并执行拷贝操作

  ③update():将指定的堆空间设置为内部存储数组

【编程实验】动态数组类的实现与重构

#ifndef DYNAMICARRAY_H
#define DYNAMICARRAY_H
#include "array.h"

namespace   DataStructureLib
{
template <typename T>
class DynamicArray:public Array<T>
{
protected:
    int m_length;

   //分配内存并拷贝数组元素
    T* copy(T* array,int len,int newlen)
    {
        T*ret =new T[newlen];

       if(ret!=NULL)
      {
       int size=(len<newlen)?len:newlen;
           for(int i=0;i<size;i++)
          {
            ret[i]=array[i];
           }
        }
       return ret;
    }

     //将指定的堆空间设置为类中的成员
    void updata(T* array,int length)
    {
        if(array!=NULL)
        { //先设置变量,再删除。确保异常安全!

            T* temp=this->m_array;

            this->m_array=array;
            this->m_length=length;

            delete []temp;
        }
        else
        {
            THROW_EXCEPTION(NotEnoughMemoryException, "Not enough memory to update DynamicArray Object ....");
        }

    }


    //对象构造时的初始化操作
        void init(T* array,int length)
        {
            m_array=array;
            if(m_array!=NULL)
            {
                 m_length=length;
            }
           else
            {
                THROW_EXCEPTION(NotEnoughMemoryException,"No Enough Memory to Create DynamicArray...");
            }
        }
public:
    DynamicArray(int length)
    {
//        m_array=new T[length];
//        if(m_array!=NULL)
//        {
//             m_length=length;
//        }
//       else
//        {
//            THROW_EXCEPTION(NotEnoughMemoryException,"No Enough Memory to Create DynamicArray...");
//        }
          init(new T[length],length );

    }

    DynamicArray(const DynamicArray<T>&  obj)
    {


        /////////////////////
//        m_array=new T[obj.length()];
//        if(m_array!=NULL)
//        {

//             for(int i=0;i<obj.length();i++)
//             {
//                  this->m_array[i]=obj.m_array[i];
//             }
//             m_length=obj.length();
//        }
//       else
//        {
//            THROW_EXCEPTION(NotEnoughMemoryException,"No Enough Memory to Create DynamicArray...");
//        }
       T* array= copy(obj.m_array,obj.m_length,obj.m_length);

       init(array,obj.m_length);
    }

    DynamicArray& operator =(DynamicArray & obj)
    {
        //delete m_array [];
        //这里不能先delete[] this->m_array,再
        //赋值,因为delete可能会引起T调用析构函数,而如果在析构函数中抛出异常,以下对
        //成员变量的赋值都将无法进行,从而造成函数异常时的不安全。因此,正确的顺序应该是
        //先对成员变量赋值,最后再释放m_array的旧空间。

         if(this!=&obj)
         {
             //1. 分配新内存
//             T* array=new T[obj.length()];
             //2. 拷贝数组的
//             for(int i=0;i<obj.length();i++)
//             {
//                 array[i]=obj[i];
//             }
              //3. 设置变量
//             T* temp=this->m_array;//先设置参数,再删除m_array,以确保异常安全

//             this->m_length=obj.length();
//             m_array=array;

//             delete    []temp;


             /***********重构后**************/
             T* array=copy(obj,obj.length(),obj.length());
             updata(array,obj.m_length);
         }

        return *this;
    }

    int length() const
    {
        return m_length;
    }

    void resize(int length)
    {
        if(m_length!=length)
        {
//            int size=(m_length<length)?m_length:length;

//            T* array=new T[size];

//            if(array!=NULL)
//            {
//                for(int i=0;i<size;i++)
//                {
//                    array[i]=m_array[i];
//                }

//                T* temp=m_array;

//                m_array=array;
//                m_length=length;

//                delete []temp;
//            }
//            else
//            {
//                THROW_EXCEPTION(NotEnoughMemoryException, "Not enough memory to resize Object ....");
//            }

           T* array= copy(this->m_array,this->m_length,length);
           updata(array,length);
        }
    }

    ~DynamicArray()
    {
        delete []m_array;
    }
};
}
#endif // DYNAMICARRAY_H