1. StaticList设计要点
类模板
- 使用原生数组作为顺序存储空间
- 使用模板参数决定数组大小
template <typename T,int N>
class StaticList : public SeqList<T>
{
protected:
T m_space[N];//顺序存储空间,N为模板参数
public:
StaticList();//指定父亲成员的具体值
int capacity() const;
};
1.1 实现
#include "SeqList.h"
namespace DragonLib
{
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
1.2具体测试
#include <iostream>
#include "StaticList.h"
using namespace std;
using namespace DragonLib;
int main()
{
StaticList<int,5> l;
for(int i=0;i<l.capacity();i++)
{
l.insert(0,i);
}
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;
}
return 0;
}
1.3 测试结果
可以看出i不合法,异常出现在SeqList.h 第85行
也就是这里出现异常:越界异常
2. DynamicList设计要点
类模板
- 申请连续堆空间作为顺序存储空间
- 动态设置顺序存储空间的大小
- 保证重置顺序存储空间时的异常安全性
2.1 DynamicList设计要点
函数异常安全的概念
- 不泄露任何资源
- 不允许破坏数据
函数异常安全的基本保证
如果异常被抛出
- 对象内的任何成员任然能保持有效状态
- 没有数据的破坏及资源泄露
template <typename T>
class DynamicList : public SeqList<T>
{
protected:
int m_capacity; //记录顺序存储空间的大小
public:
DynamicList(int capacity);//申请空间
int capacity() const;
/* 重新设置顺序存储空间的大小 */
void resize(int capacity);
~DynamicList();//归还空间
};
2.2 实现
#ifndef DYNAMICLIST_H
#define DYNAMICLIST_H
#include "SeqList.h"
#include "Exception.h"
namespace DragonLib
{
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 object...");
}
}
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;//释放原来的m_array空间
}
else
{
THROW_EXCEPTION(NoEnoughMemoryException,"No memory to resize DynamicList object...");
}
}
}
~DynamicList()//归还空间
{
delete[] this->m_array;
}
};
}
#endif // DYNAMICLIST_H
2.3 玄机
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;//释放原来的m_array空间
}
else
{
THROW_EXCEPTION(NoEnoughMemoryException,"No memory to resize DynamicList object...");
}
}
}
这里用了T* temp = this->m_array,而不是直接用m_array,这样子做到了异常安全。如果用m_array的话,在赋值之前就需要先delete,万一抛异常,下面的赋值操作就没有执行,并不能保证现在的线性表能否直接使用
3. 小结
- StaticList通过模板参数定义顺序存储空间
- DynamicList通过动态内存申请定义顺序存储空间
- DynamicList支持动态重置顺序存储空间的大小
- DynamicList中的resize()函数实现需要保证异常安全