1. 程式人生 > >陣列類的建立(下)

陣列類的建立(下)

建立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