在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表示开辟多大的空间。
其他的函数之前的博客实现过,我们这里就不再重复实现了。
本文出自 “Han Jing's Blog” 博客,请务必保留此出处http://10740184.blog.51cto.com/10730184/1750309