1. 程式人生 > >StaticList 和 DynamicList(七)

StaticList 和 DynamicList(七)

動態 object 要點 ins list cap creat .cpp http

我們在上節博客中說到,在 SeqList 下又可以衍生出 StaticListDynamicList 兩個子類。那麽我們今天就來看看這兩個子類,它們是如何實現的以及它們之間有何區別。

A、StaticList 的設計要點:首先必須是一個類模板。其次是使用原生數組作為順序存儲空間,最後是使用模板參數決定數組大小。定義如下

template < typename T, int N >
class StaticList : public SeqList<T>
{
protected:
    T m_space[N];            // 順序存儲空間,N 為模板參數
public:
    StaticList();            // 指定父類成員的具體值
    int capacity() const;
};

我們下來來實現 StaticList ,代碼如下


StaticList.h 源碼

#ifndef STATICLIST_H
#define STATICLIST_H

#include "Seqlist.h"

namespace DTLib
{

template < typename T, int N >
class StaticList : public SeqList<T>
{
protected:
    T m_space[N];   // 順序存儲空間,N 為模板參數
public:
    StaticList()    // 指定父類成員的具體值
    {
        this->m_array = m_space;

        this->m_length = 0;
    }

    int capacity() const
    {
        return N;
    }
};

}

#endif // STATICLIST_H

我們來寫個測試代碼測試下這個 StaticList ,main.cpp 代碼如下

#include <iostream>
#include "StaticList.h"

using namespace std;
using namespace DTLib;

int main()
{
    StaticList<int, 5> l;

    for(int i=0; i<l.capacity(); i++)
    {
        l.insert(0, i);
    }

    for(int i=0; i<l.capacity(); i++)
    {
        cout << l[i] << endl;
    }

    l[0] *= l[0];

    for(int i=0; i<l.capacity(); i++)
    {
        cout << l[i] << endl;
    }

    try
    {
        l[5] = 5;
    }
    catch(const Exception& e)
    {
        cout << e.message() << endl;
        cout << e.location() << endl;
    }

    return 0;
}

我們來看看輸出結果

技術分享圖片

結果正是我們想要的,這個 StaticList 類已經實現完畢。接下來我們再來實現 DynamicList 類。

B、DynamicList 類的設計要點:它也必須得是一個類模板。申請連續堆空間作為順序存儲空間;動態設置順序存儲空間的大小;保證重置順序存儲空間時的異常安全性

a> 函數異常安全的概念:1、不泄露任何資源;2、不允許破壞數據。

b> 函數異常安全的基本保證,如果對象被拋出:對象內的任何成員仍然能保持有效狀態;沒有數據的破壞及資源泄漏。

下來我們來看看它的定義

template < typename T >
class DynamicList : public SeqList<T>
{
protected:
    int m_capacity;    // 順序存儲空間的大小
public:
    DynamicList(int capacity);    // 申請空間
    int capacity() const;
    
    // 重新設置順序存儲空間的大小
    void resize(int capacity);
    ~DynamicList();    // 歸還空間
};

下來我們來實現這個 DynamicList


DynamicList.h 源碼

#ifndef DYNAMICLIST_H
#define DYNAMICLIST_H

#include "SeqList.h"
#include "Exception.h"

namespace DTLib
{

template < typename T >
class DynamicList : public SeqList<T>
{
protected:
    int m_capacity;     // 順序存儲空間的大小
public:
    DynamicList(int capacity)   // 申請空間
    {
        this->m_array = new T[capacity];

        if( this->m_array != NULL )
        {
            this->m_length = 0;
            this->m_capacity = capacity;
        }
        else
        {
            THROW_EXCEPTION(NoEnoughMemoryException, "No memory to create DynamicList ...");
        }
    }

    int capacity() const
    {
        return m_capacity;
    }

    void resize(int capacity)
    {
        if( capacity != m_capacity )
        {
            T* array = new T[capacity];

            if( array != NULL )
            {
                int length = (this->m_length < capacity ? this->m_length : capacity);

                for(int i=0; i<length; i++)
                {
                    array[i] = this->m_array[i];
                }

                T* temp = this->m_array;

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

                delete[] temp;
            }
            else
            {
                THROW_EXCEPTION(NoEnoughMemoryException, "No memory to resize DynamicList Object ...");
            }
        }
    }

    ~DynamicList()
    {
        delete[] this->m_array;
    }

};

}

#endif // DYNAMICLIST_H

我們同樣還是寫個示例代碼來驗證下這個 DynamicList 類,main.cpp 代碼如下

#include <iostream>
#include "DynamicList.h"

using namespace std;
using namespace DTLib;

int main()
{
    DynamicList<int> l(5);

    for(int i=0; i<l.capacity(); i++)
    {
        l.insert(0, i);
    }

    for(int i=0; i<l.length(); i++)
    {
        cout << l[i] << endl;
    }

    l[0] *= l[0];

    for(int i=0; i<l.length(); i++)
    {
        cout << l[i] << endl;
    }

    try
    {
        l[5] = 5;
    }
    catch(const Exception& e)
    {
        cout << e.message() << endl;
        cout << e.location() << endl;

        l.resize(10);

        l.insert(4, 40);
    }

    l[5] = 5;

    for(int i=0; i<l.length(); i++)
    {
        cout << l[i] << endl;
    }

    l.resize(3);

    for(int i=0; i<l.length(); i++)
    {
        cout << l[i] << endl;
    }

    return 0;
}

我們來看看編譯結果

技術分享圖片

結果已經正確輸出了。那麽回到我們之前的問題:是否能將 DynamicList 作為 StaticList 的子類實現呢?答案肯定是不行的,因為 DynamicList 和 StaticList 兩個類在存儲結構上完全是不同的。因此他們是等價的,所以不能將 DynamicList 作為 StaticList 的子類實現。通過今天對 DynamicListStaticList 的學習,總結如下:1、StaticList 通過模板參數定義順序存儲空間;2、DynamicList 通過動態內存申請定義順序存儲空間;3、DynamicList 支持動態重置順序存儲空間的大小;4、DynamicList 中的 resize() 函數實現需要保證異常安全。

StaticList 和 DynamicList(七)