1. LinkList的定义
template <typename T>
{
class LinkList : public List<T>
{
protected:
struct Node : public Object
{
T value;
Node* next;
};
Node m_header;
int m_length;
public:
LinkList();
};
}
1.1 实现
#ifndef LINKLIST_H
#define LINKLIST_H
#include "List.h"
#include "Exception.h"
namespace DragonLib
{
template <typename T>
class LinkList : public List<T>
{
protected:
struct Node : public Object
{
T value;
Node* next;
};
mutable struct
{
char reserved[sizeof(T)];
Node* next;
}m_header;
int m_length;
public:
LinkList()
{
m_header.next = NULL;
m_length = 0;
}
bool insert(const T& e)
{
return insert(m_length,e);
}
bool insert(int i,const T& e)
{
bool ret = ((0<=i) && (i<=m_length));
if(ret)
{
Node* node = new Node();
if(node != NULL)
{
Node* current = &m_header;
for(int p=0;p<i;p++)
{
current = current->next;
}
node->value = e;
node->next = current->next;
current->next = node;
m_length++;
}
else
{
THROW_EXCEPTION(NoEnoughMemoryException,"No memory to insert new element!");
}
}
return ret;
}
bool remove(int i)
{
bool ret = ((0<=i) && (i<m_length));
if(ret)
{
Node* current = &m_header;
for(int p=0;p<i;p++)
{
current = current->next;
}
Node* toDel = current->next;
current->next = toDel->next;
delete toDel;
m_length--;
}
return ret;
}
bool set(int i,const T& e)
{
bool ret = ((0<=i) && (i<m_length));
if(ret != NULL)
{
Node* current = &m_header;
for(int p=0;p<i;p++)
{
current = current->next;
}
current->next->value = e;
}
return ret;
}
T get(int i)const
{
T ret;
if(get(i,ret))
{
return ret;
}
else
{
THROW_EXCEPTION(IndexOutOfBoundsException,"Invalid parameter i to get element...");
}
return ret;
}
bool get(int i,T& e) const
{
bool ret = ((0<=i) && (i<m_length));
if(ret != NULL)
{
Node* current = &m_header;
for(int p=0;p<i;p++)
{
current = current->next;
}
e = current->next->value;
}
return ret;
}
int length() const
{
return m_length;
}
void clear()
{
while(m_header.next)
{
Node* toDel = m_header.next;//这四行逻辑很妙
m_header.next = toDel->next;
delete toDel;
}
m_length = 0;
}
~LinkList()
{
clear();
}
};
}
#endif // LINKLIST_H
1.3 测试
class Test
{
public:
Test()
{
throw 0;
}
};
int main()
{
LinkList<Test> list;
cout << "Alone" << endl;
return 0;
}
在main函数上面我们写了一个有问题的Test类,会抛异常。执行LinkList list;时,虽然没有定义Test对象,但是定义list时会触发构造函数:
注:Node m_header;时,会调用Node结构体,又会调用到泛型T,即Test,然而Test是个会抛异常的类!所以会抛异常!
1.4 解决
struct Node : public Object
{
T value;
Node* next;
};
mutable struct
{
char reserved[sizeof(T)];
Node* next;
}m_header;
int m_length;
2. 小结
- 通过类模板实现链表,包含头结点成员和长度成员
- 定义结点类型,并通过堆中的结点对象构成链式存储
- 为了避免构造错误的隐患,头结点类型需要重新定义
- 代码优化是编码完成后必不可少的环节