(比上一章节的数组类仅多了 Begin() 和 End() 方法)
//数组类
template
class MyArray
{
private:
int m_nTotalSize; //数组总长度
int m_nValidSize; //数组有效长度,即当前元素数
T * m_pData; //数据指针
public:
//构造函数
MyArray(int nSize=2) //假设默认数组长度为2
{
m_pData=new T[nSize];
m_nTotalSize=nSize;
m_nValidSize=0;
}
//获取数组有效长度
int GetValidSize()
{
return m_nValidSize;
}
//获取数组总长度
int GetTotalSize()
{
return m_nTotalSize;
}
//返回某一位置元素
T Get(int pos)
{
return m_pData[pos];
}
//添加一个元素
void Add(T value)
{
if(m_nValidSize
//链表结点数据结构
template
struct Unit
{
T value;
Unit * next;
};
//链表类
template
class MyLink
{
private:
Unit * head; //链表头
Unit * tail; //链表尾
Unit * prev; //指向最后一个结点
public:
//构造函数
MyLink()
{
head=tail=prev=NULL;
}
//添加一个结点
void Add(const T &value)
{
Unit *u=new Unit();
u->value=value;
u->next=NULL;
if(head==NULL)
{
head=u;
prev=u;
}
else
{
prev->next=u;
prev=u;
}
tail=u->next;
}
//返回头指针
Unit* Begin()
{
return head;
}
//返回尾指针
Unit* End()
{
return tail;
}
//析构函数
virtual ~MyLink()
{
Unit *prev=head;
Unit *next=NULL;
while(prev!=tail)
{
next=prev->next;
delete prev;
prev=next;
}
}
};
可以看出,MyArray 是模板元素 T 的数组类,MyLink 是模板元素 T 的链表类,以 struct Unit 为一个链表单元。那么如何以 MyArray 和 MyLink 为基础,完成一个共同的显示函数呢?首先从需求出发,逆向考虑,
//泛型显示函数
template
void Display(T Start,T End)
{
cout<
该函数的模板参数即为迭代器类型,该泛型函数能够输出从迭代器 Start 至 End 之间的所有元素,指针支持 ++ 和 * 操作。Display() 函数与具体的容器没有直接关联,但是间接关联是必需的,对于 MyArray 来说,该参数相当于数组类中的 T* 操作,对于 Mylink 来说,该参数相当于链表类当中的 Unittemplate
class ArrayIterator
{
private:
T * t;
public:
//构造函数
ArrayIterator(T * t)
{
this->t=t;
}
//重载!=
bool operator != (const ArrayIterator &it)
{
return this->t!=it.t;
}
//重载++
void operator ++ (int)
{
t++;
}
//重载取值符*
T operator *()
{
return *t;
}
};
可以看出,ArrayIterator 类是对 T* 的再封装,必须重载 operator !=、++、* 操作符,这是由于 Display 泛型显示函数需要用到这些操作符。template
class LinkIterator
{
private:
T *t;
public:
//构造函数
LinkIterator(T *t)
{
this->t=t;
}
//重载!=
bool operator !=(const LinkIterator &it)
{
return this->t!=it.t;
}
//重载++
void operator ++(int)
{
t=t->next;
}
//重载取值符*
T operator *()
{
return *t;
}
};
可以看出 operator !=、operator * 的重载内容与 ArrayIterator 一致,只有 operator ++ 不同,因为这里链表并不像数组一样连续存储,它是指针的转向,所有不能是 t++ ,而应该是 t=t->next。//重载全局函数operator <<
template
ostream& operator<<(ostream& os,const Unit &u)
{
os<
int main()
{
MyArray ary;
MyLink link;
ary.Add(1.1);
ary.Add(2.2);
ary.Add(3.3);
link.Add(1);
link.Add(2);
link.Add(3);
ArrayIterator aryStart(ary.Begin());
ArrayIterator aryEnd(ary.End());
//注意!!这里两个尖括号要分开
LinkIterator > linkStart(link.Begin());
LinkIterator > linkEnd(link.End());
Display(aryStart,aryEnd);
Display(linkStart,linkEnd);
return 0;
}
过程可以描述为:定义一个容器对象,向其中添加数据,获得迭代器对象 Start 、End,最后调用泛型显式函数 Display 完成数据的输出。#include
using namespace std;
//数组类
template
class MyArray
{
private:
int m_nTotalSize; //数组总长度
int m_nValidSize; //数组有效长度,即当前元素数
T * m_pData; //数据指针
public:
//构造函数
MyArray(int nSize=2) //假设默认数组长度为2
{
m_pData=new T[nSize];
m_nTotalSize=nSize;
m_nValidSize=0;
}
//获取数组有效长度
int GetValidSize()
{
return m_nValidSize;
}
//获取数组总长度
int GetTotalSize()
{
return m_nTotalSize;
}
//返回某一位置元素
T Get(int pos)
{
return m_pData[pos];
}
//添加一个元素
void Add(T value)
{
if(m_nValidSize
struct Unit
{
T value;
Unit * next;
};
//链表类
template
class MyLink
{
private:
Unit * head; //链表头
Unit * tail; //链表尾
Unit * prev; //指向最后一个结点
public:
//构造函数
MyLink()
{
head=tail=prev=NULL;
}
//添加一个结点
void Add(const T &value)
{
Unit *u=new Unit();
u->value=value;
u->next=NULL;
if(head==NULL)
{
head=u;
prev=u;
}
else
{
prev->next=u;
prev=u;
}
tail=u->next;
}
//返回头指针
Unit* Begin()
{
return head;
}
//返回尾指针
Unit* End()
{
return tail;
}
//析构函数
virtual ~MyLink()
{
Unit *prev=head;
Unit *next=NULL;
while(prev!=tail)
{
next=prev->next;
delete prev;
prev=next;
}
}
};
//泛型显示函数
template
void Display(T Start,T End)
{
cout<
class ArrayIterator
{
private:
T * t;
public:
//构造函数
ArrayIterator(T * t)
{
this->t=t;
}
//重载!=
bool operator != (const ArrayIterator &it)
{
return this->t!=it.t;
}
//重载++
void operator ++ (int)
{
t++;
}
//重载取值符*
T operator *()
{
return *t;
}
};
template
class LinkIterator
{
private:
T *t;
public:
//构造函数
LinkIterator(T *t)
{
this->t=t;
}
//重载!=
bool operator !=(const LinkIterator &it)
{
return this->t!=it.t;
}
//重载++
void operator ++(int)
{
t=t->next;
}
//重载取值符*
T operator *()
{
return *t;
}
};
//重载全局函数operator <<
template
ostream& operator<<(ostream& os,const Unit &u)
{
os< ary;
MyLink link;
ary.Add(1.1);
ary.Add(2.2);
ary.Add(3.3);
link.Add(1);
link.Add(2);
link.Add(3);
ArrayIterator aryStart(ary.Begin());
ArrayIterator aryEnd(ary.End());
//注意!!这里两个尖括号要分开
LinkIterator > linkStart(link.Begin());
LinkIterator > linkEnd(link.End());
Display(aryStart,aryEnd);
Display(linkStart,linkEnd);
return 0;
}
//数组类
template
class MyArray
{
private:
int m_nTotalSize; //数组总长度
int m_nValidSize; //数组有效长度,即当前元素数
T * m_pData; //数据指针
public:
//构造函数
MyArray(int nSize=2) //假设默认数组长度为2
{
m_pData=new T[nSize];
m_nTotalSize=nSize;
m_nValidSize=0;
}
//数组迭代器
class ArrayIterator
{
private:
T * t;
public:
//构造函数
ArrayIterator(T * t)
{
this->t=t;
}
//重载!=
bool operator != (const ArrayIterator &it)
{
return this->t!=it.t;
}
//重载++
void operator ++ (int)
{
t++;
}
//重载取值符*
T operator *()
{
return *t;
}
};
//获取数组有效长度
int GetValidSize()
{
return m_nValidSize;
}
//获取数组总长度
int GetTotalSize()
{
return m_nTotalSize;
}
//返回某一位置元素
T Get(int pos)
{
return m_pData[pos];
}
//添加一个元素
void Add(T value)
{
if(m_nValidSize
注意!与原代码相比少了很多尖括号,并且由于模板编程的规则有好几处稍许变化的地方,希望读者能留心发现。//链表类
template
class MyLink
{
public:
//链表结点数据结构
struct Unit
{
T value;
Unit * next;
};
//链表类迭代器
class LinkIterator
{
private:
Unit *u;
public:
//构造函数
LinkIterator(Unit *u)
{
this->u=u;
}
//重载!=
bool operator !=(const LinkIterator &it)
{
return this->u!=it.u;
}
//重载++
void operator ++(int)
{
u=u->next;
}
//重载取值符*
Unit operator *()
{
return *this->u;
}
};
//重载全局函数operator <<
friend ostream& operator<<(ostream& os,typename MyLink::Unit& u)
{
os<value=value;
u->next=NULL;
if(head==NULL)
{
head=u;
prev=u;
}
else
{
prev->next=u;
prev=u;
}
tail=u->next;
}
//返回头指针
Unit * Begin()
{
return head;
}
//返回尾指针
Unit * End()
{
return tail;
}
//析构函数
virtual ~MyLink()
{
if(head!=NULL)
{
Unit *prev=head;
Unit *next=NULL;
while(prev!=tail)
{
next=prev->next;
delete prev;
prev=next;
}
}
}
private:
Unit * head; //链表头
Unit * tail; //链表尾
Unit * prev; //指向最后一个结点
};
由于该 struct Unit 结构体为该链表类专用,因此也一并放进了 MyArray 类中。值得注意的是,全局函数 cout<< 的重载也被放了进来,因为只有用到这个链表类时,才会有 cout<int main()
{
MyArray ary;
MyLink link;
ary.Add(1.1f);
ary.Add(2.2f);
ary.Add(3.3f);
link.Add(1);
link.Add(2);
link.Add(3);
MyArray::ArrayIterator aryStart(ary.Begin());
MyArray::ArrayIterator aryEnd(ary.End());
MyLink::LinkIterator linkStart(link.Begin());
MyLink::LinkIterator linkEnd(link.End());
Display(aryStart,aryEnd);
Display(linkStart,linkEnd);
return 0;
}
#include
using namespace std;
//数组类
template
class MyArray
{
private:
int m_nTotalSize; //数组总长度
int m_nValidSize; //数组有效长度,即当前元素数
T * m_pData; //数据指针
public:
//构造函数
MyArray(int nSize=2) //假设默认数组长度为2
{
m_pData=new T[nSize];
m_nTotalSize=nSize;
m_nValidSize=0;
}
//数组迭代器
class ArrayIterator
{
private:
T * t;
public:
//构造函数
ArrayIterator(T * t)
{
this->t=t;
}
//重载!=
bool operator != (const ArrayIterator &it)
{
return this->t!=it.t;
}
//重载++
void operator ++ (int)
{
t++;
}
//重载取值符*
T operator *()
{
return *t;
}
};
//获取数组有效长度
int GetValidSize()
{
return m_nValidSize;
}
//获取数组总长度
int GetTotalSize()
{
return m_nTotalSize;
}
//返回某一位置元素
T Get(int pos)
{
return m_pData[pos];
}
//添加一个元素
void Add(T value)
{
if(m_nValidSize
class MyLink
{
public:
//链表结点数据结构
struct Unit
{
T value;
Unit * next;
};
//链表类迭代器
class LinkIterator
{
private:
Unit *u;
public:
//构造函数
LinkIterator(Unit *u)
{
this->u=u;
}
//重载!=
bool operator !=(const LinkIterator &it)
{
return this->u!=it.u;
}
//重载++
void operator ++(int)
{
u=u->next;
}
//重载取值符*
Unit operator *()
{
return *this->u;
}
};
//重载全局函数operator <<
friend ostream& operator<<(ostream& os,typename MyLink::Unit& u)
{
os<value=value;
u->next=NULL;
if(head==NULL)
{
head=u;
prev=u;
}
else
{
prev->next=u;
prev=u;
}
tail=u->next;
}
//返回头指针
Unit * Begin()
{
return head;
}
//返回尾指针
Unit * End()
{
return tail;
}
//析构函数
virtual ~MyLink()
{
if(head!=NULL)
{
Unit *prev=head;
Unit *next=NULL;
while(prev!=tail)
{
next=prev->next;
delete prev;
prev=next;
}
}
}
private:
Unit * head; //链表头
Unit * tail; //链表尾
Unit * prev; //指向最后一个结点
};
//泛型显示函数
template
void Display(T Start,T End)
{
cout< ary;
MyLink link;
ary.Add(1.1f);
ary.Add(2.2f);
ary.Add(3.3f);
link.Add(1);
link.Add(2);
link.Add(3);
MyArray::ArrayIterator aryStart(ary.Begin());
MyArray::ArrayIterator aryEnd(ary.End());
MyLink::LinkIterator linkStart(link.Begin());
MyLink::LinkIterator linkEnd(link.End());
Display(aryStart,aryEnd);
Display(linkStart,linkEnd);
return 0;
}
注意!上述代码我在 VS 2010 下编译正确,运行正确,但在 CodeBlocks 用 GNU GCC 编译器编译时报错,难道是 GCC 编译器的bug?希望有知道的大神赐教。#include
#include
using namespace std;
int main()
{
cout<<"请输入数据(如1 2 3,):";
istream_iterator Start(cin); //建立键盘输入流
istream_iterator End; //建立输入流结束迭代器
while(1)
{
cout<<*Start<
程序执行结果为:
#include
#include
using namespace std;
int main()
{
ostream_iterator Out(cout,"\t");
*Out=1;
Out++;
*Out=2;
Out++;
*Out=3;
Out++;
return 0;
}
程序执行结果为:template
void Replace(ForwardIterator first,ForwardIterator last,const T& old_value,const T& new_value)
{
for(;first!=last;first++)
if(*first==old_value)
*first=new_value;
}
这里的 first,就是 ForwardIterator 的模型,其需求包括 first!=last、first++、*first==old_value、*first=new_value。这样,Forward Iterator 的需求概括为:能进行构造或默认构造,能被复制或赋值,能进行相等性比较,能进行逐步前向移动,能进行读取值(但不能进行改写)。前向迭代器包含了输入和输出迭代器两者的所有功能,加上还可以多次解析一个迭代器指定的位置,因此可以对一个值多次进行读写。顾名思义,前向迭代器只能向前移动。但是 STL 本事并没有专门为前向迭代器预定义的迭代器。