在C或C++里,我们已经学会了如何实现一个静态顺序表了,那为何还要引入模版类来实现静态顺序表呢?首先,我们看,在未引入模版前,我们在C++里是这样定义一个静态顺序表的:

typedef int DataType;    //此时我定义的是int型

class SeqList
{
    DataType* _array;
    size_t _size;
    size_t _capacity;
}

    我们若要定义char型或者其他类型的,可以采用typedef了,这就是使用typedef的优势之处。另外,还利于统一管理程序代码,增加代码的可维护性。


    可是,有时候我们会不会遇到这样的问题呢:

void Test()
{
    SeqList s1;    //此时s1我想定义成为char型
    SeqList s2;    //此时s2我想定义成为非char型
}

    这时候,若我们使用typedef换来换去的,难免使得代码混乱或者出错。若是再定义一个类来实现另外一个类型的静态顺序表,这时候代码两处相似度极高,也不利于维护。因此,我们引入模板,模板类的实例化可以轻而易举地解决好这个问题。

代码如下:


#include<iostream>
using namespace std;
#include<string>
#include<assert.h>

template<class T>

class SeqList
{
private:
    T* _array;
    size_t _size;
    size_t _capacity;
    
public:
    SeqList()
        :_array(NULL)
        , _size(0)
        , _capacity(0)
    {}

    SeqList(const SeqList<T>& s)
    {
        _array = new T[s._size];
        for (size_t i = 0; i < s._size; i++)
        {
            _array[i] = s._array[i];
        }
        _size = s._size;
        _capacity = s._size;
    }

    SeqList<T>& operator=(SeqList<T> s)
    {
        if (&s != this)
        {
            swap(_array, s._array);
            swap(_size, s._size);
            swap(_capacity, s._capacity);
        }
        return *this;
    }

    ~SeqList()
    {
        if (_array)
        {
            delete[] _array;
        }
    }

    //扩容
    void _CheckCapacity(size_t n)
    {
        if (n > _capacity)
        {
            _capacity = n > 2 * _capacity + 3 ? n : 2 * _capacity + 3;
            /*_array = (T*)realloc(_array, sizeof(T)* _capacity);*/
            //不可行!realloc对于自定义类型未调用构造函数初始化对象,随机值会崩溃。
            
            T* tmp = new T[_capacity];
            if (_array)
            {
                /*memcpy(tmp, _array, sizeof(T)* _size);*/
                //不可行!对于长字符串重新开辟空间拷贝析构两次崩溃
                for (size_t i = 0; i < _size; i++)
                {
                    tmp[i] = _array[i];
                }
            }
            delete[] _array;
            _array = tmp;
        }
    }

    //打印
    void PrintSeqList()
    {
        for (size_t i = 0; i < _size; i++)
        {
            cout << _array[i] << "  ";
        }  
        cout << endl;
    }

    //尾插
    void PushBack(const T& x)
    {
        _CheckCapacity(_size + 1);
        _array[_size++] = x;
    }

    //operator[]
    T& operator[](size_t index)
    {
        assert(index < _size);
        return _array[index];
    }

    //请求空间
    void Reserve(size_t n)
    {
        _CheckCapacity(n);
    }
};

void Test()
{
    SeqList<int> s1;
    s1.PushBack(1);
    s1.PushBack(2);
    s1.PushBack(3);
    s1.PushBack(4);
    s1.PushBack(5);
    s1.PrintSeqList();

    SeqList<string> s2;
    s2.PushBack("xxx");
    s2.PushBack("xxx");
    s2.PushBack("xxx");
    s2.PushBack("xxx");
    s2.PushBack("xxx");
    s2.PrintSeqList();
            
    SeqList<string> s3(s2);
    s3[0] = "yyy";
    s3.PrintSeqList();    
}


int main()
{
    Test();
    system("pause");
    return 0;
}

    在这里,我们关注下reserve()函数,接口实现请求一个容量。我们查看cplusplus.com可以找vector(顺序表)中的reserve(size_t n)。n表示开辟多大的空间。

    其他的函数之前的博客实现过,我们这里就不再重复实现了。