标签:
(比上一章节的数组类仅多了 Begin() 和 End() 方法)
//数组类
template <class T>
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<m_nTotalSize) //若数组未满
{
m_pData[m_nValidSize]=value;
m_nValidSize++;
}
else //数组满时动态增加数组大小
{
T * pOldData=m_pData; //保存当前数据指针
m_pData=new T[m_nTotalSize*2]; //原先数组空间大小扩大两倍
for(int i=0;i<m_nTotalSize;i++) //拷贝原先数据
{
m_pData[i]=pOldData[i];
}
m_nTotalSize*=2; //当前数组总长度更新
delete pOldData; //释放旧数组占用的内存
m_pData[m_nValidSize]=value; //添加新元素
m_nValidSize++; //更新数组有效程度
}
}
//返回头指针
T * Begin()
{
return m_pData;
}
//返回尾指针
T * End()
{
return m_pData+m_nValidSize;
}
virtual ~MyArray()
{
if(m_pData!=NULL)
{
delete []m_pData;
m_pData=NULL;
}
}
};
//链表结点数据结构
template <class T>
struct Unit
{
T value;
Unit * next;
};
//链表类
template <class T>
class MyLink
{
private:
Unit<T> * head; //链表头
Unit<T> * tail; //链表尾
Unit<T> * prev; //指向最后一个结点
public:
//构造函数
MyLink()
{
head=tail=prev=NULL;
}
//添加一个结点
void Add(const T &value)
{
Unit<T> *u=new Unit<T>();
u->value=value;
u->next=NULL;
if(head==NULL)
{
head=u;
prev=u;
}
else
{
prev->next=u;
prev=u;
}
tail=u->next;
}
//返回头指针
Unit<T>* Begin()
{
return head;
}
//返回尾指针
Unit<T>* End()
{
return tail;
}
//析构函数
virtual ~MyLink()
{
Unit<T> *prev=head;
Unit<T> *next=NULL;
while(prev!=tail)
{
next=prev->next;
delete prev;
prev=next;
}
}
};可以看出,MyArray 是模板元素 T 的数组类,MyLink 是模板元素 T 的链表类,以 struct Unit 为一个链表单元。那么如何以 MyArray 和 MyLink 为基础,完成一个共同的显示函数呢?首先从需求出发,逆向考虑,
//泛型显示函数
template <class T>
void Display(T Start,T End)
{
cout<<endl;
for(T i=Start;i!=End;i++)
{
cout<<*i<<" ";
}
cout<<endl;
}该函数的模板参数即为迭代器类型,该泛型函数能够输出从迭代器 Start 至 End 之间的所有元素,指针支持 ++ 和 * 操作。Display() 函数与具体的容器没有直接关联,但是间接关联是必需的,对于 MyArray 来说,该参数相当于数组类中的 T* 操作,对于 Mylink 来说,该参数相当于链表类当中的 Unit<T>* 操作,所以该参数就相当于容器中元素的指针。template<class T>
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 T>
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 <class T>
ostream& operator<<(ostream& os,const Unit<T> &u)
{
os<<u.value;
return os;
}
int main()
{
MyArray<float> ary;
MyLink<int> link;
ary.Add(1.1);
ary.Add(2.2);
ary.Add(3.3);
link.Add(1);
link.Add(2);
link.Add(3);
ArrayIterator<float> aryStart(ary.Begin());
ArrayIterator<float> aryEnd(ary.End());
//注意!!这里两个尖括号要分开
LinkIterator<Unit<int> > linkStart(link.Begin());
LinkIterator<Unit<int> > linkEnd(link.End());
Display(aryStart,aryEnd);
Display(linkStart,linkEnd);
return 0;
}过程可以描述为:定义一个容器对象,向其中添加数据,获得迭代器对象 Start 、End,最后调用泛型显式函数 Display 完成数据的输出。#include <iostream>
using namespace std;
//数组类
template <class T>
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<m_nTotalSize) //若数组未满
{
m_pData[m_nValidSize]=value;
m_nValidSize++;
}
else //数组满时动态增加数组大小
{
T * pOldData=m_pData; //保存当前数据指针
m_pData=new T[m_nTotalSize*2]; //原先数组空间大小扩大两倍
for(int i=0;i<m_nTotalSize;i++) //拷贝原先数据
{
m_pData[i]=pOldData[i];
}
m_nTotalSize*=2; //当前数组总长度更新
delete pOldData; //释放旧数组占用的内存
m_pData[m_nValidSize]=value; //添加新元素
m_nValidSize++; //更新数组有效程度
}
}
//返回头指针
T * Begin()
{
return m_pData;
}
//返回尾指针
T * End()
{
return m_pData+m_nValidSize;
}
virtual ~MyArray()
{
if(m_pData!=NULL)
{
delete []m_pData;
m_pData=NULL;
}
}
};
//链表结点数据结构
template <class T>
struct Unit
{
T value;
Unit * next;
};
//链表类
template <class T>
class MyLink
{
private:
Unit<T> * head; //链表头
Unit<T> * tail; //链表尾
Unit<T> * prev; //指向最后一个结点
public:
//构造函数
MyLink()
{
head=tail=prev=NULL;
}
//添加一个结点
void Add(const T &value)
{
Unit<T> *u=new Unit<T>();
u->value=value;
u->next=NULL;
if(head==NULL)
{
head=u;
prev=u;
}
else
{
prev->next=u;
prev=u;
}
tail=u->next;
}
//返回头指针
Unit<T>* Begin()
{
return head;
}
//返回尾指针
Unit<T>* End()
{
return tail;
}
//析构函数
virtual ~MyLink()
{
Unit<T> *prev=head;
Unit<T> *next=NULL;
while(prev!=tail)
{
next=prev->next;
delete prev;
prev=next;
}
}
};
//泛型显示函数
template <class T>
void Display(T Start,T End)
{
cout<<endl;
for(T i=Start;i!=End;i++)
{
cout<<*i<<" ";
}
cout<<endl;
}
template<class T>
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 T>
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 <class T>
ostream& operator<<(ostream& os,const Unit<T> &u)
{
os<<u.value;
return os;
}
int main()
{
MyArray<float> ary;
MyLink<int> link;
ary.Add(1.1);
ary.Add(2.2);
ary.Add(3.3);
link.Add(1);
link.Add(2);
link.Add(3);
ArrayIterator<float> aryStart(ary.Begin());
ArrayIterator<float> aryEnd(ary.End());
//注意!!这里两个尖括号要分开
LinkIterator<Unit<int> > linkStart(link.Begin());
LinkIterator<Unit<int> > linkEnd(link.End());
Display(aryStart,aryEnd);
Display(linkStart,linkEnd);
return 0;
}
//数组类
template <class T>
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<m_nTotalSize) //若数组未满
{
m_pData[m_nValidSize]=value;
m_nValidSize++;
}
else //数组满时动态增加数组大小
{
T * pOldData=m_pData; //保存当前数据指针
m_pData=new T[m_nTotalSize*2]; //原先数组空间大小扩大两倍
for(int i=0;i<m_nTotalSize;i++) //拷贝原先数据
{
m_pData[i]=pOldData[i];
}
m_nTotalSize*=2; //当前数组总长度更新
delete pOldData; //释放旧数组占用的内存
m_pData[m_nValidSize]=value; //添加新元素
m_nValidSize++; //更新数组有效程度
}
}
//返回头指针
T * Begin()
{
return m_pData;
}
//返回尾指针
T * End()
{
return m_pData+m_nValidSize;
}
//析构函数
virtual ~MyArray()
{
if(m_pData!=NULL)
{
delete []m_pData;
m_pData=NULL;
}
}
};注意!与原代码相比少了很多尖括号,并且由于模板编程的规则有好几处稍许变化的地方,希望读者能留心发现。//链表类
template <class T>
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<T>::Unit& u)
{
os<<u.value;
return os;
}
//构造函数
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()
{
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<<Unit<T> 的必要,因此要一并封装。另外,为了能使 ostream 对象访问该类的私有变量,必须将这个重载函数用 friend 关键字写为友元函数。int main()
{
MyArray<float> ary;
MyLink<int> link;
ary.Add(1.1f);
ary.Add(2.2f);
ary.Add(3.3f);
link.Add(1);
link.Add(2);
link.Add(3);
MyArray<float>::ArrayIterator aryStart(ary.Begin());
MyArray<float>::ArrayIterator aryEnd(ary.End());
MyLink<int>::LinkIterator linkStart(link.Begin());
MyLink<int>::LinkIterator linkEnd(link.End());
Display(aryStart,aryEnd);
Display(linkStart,linkEnd);
return 0;
}
#include <iostream>
using namespace std;
//数组类
template <class T>
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<m_nTotalSize) //若数组未满
{
m_pData[m_nValidSize]=value;
m_nValidSize++;
}
else //数组满时动态增加数组大小
{
T * pOldData=m_pData; //保存当前数据指针
m_pData=new T[m_nTotalSize*2]; //原先数组空间大小扩大两倍
for(int i=0;i<m_nTotalSize;i++) //拷贝原先数据
{
m_pData[i]=pOldData[i];
}
m_nTotalSize*=2; //当前数组总长度更新
delete pOldData; //释放旧数组占用的内存
m_pData[m_nValidSize]=value; //添加新元素
m_nValidSize++; //更新数组有效程度
}
}
//返回头指针
T * Begin()
{
return m_pData;
}
//返回尾指针
T * End()
{
return m_pData+m_nValidSize;
}
//析构函数
virtual ~MyArray()
{
if(m_pData!=NULL)
{
delete []m_pData;
m_pData=NULL;
}
}
};
//链表类
template <class T>
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<T>::Unit& u)
{
os<<u.value;
return os;
}
//构造函数
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()
{
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 <class T>
void Display(T Start,T End)
{
cout<<endl;
for(T i=Start;i!=End;i++)
{
cout<<*i;
cout<<" ";
}
cout<<endl;
}
int main()
{
MyArray<float> ary;
MyLink<int> link;
ary.Add(1.1f);
ary.Add(2.2f);
ary.Add(3.3f);
link.Add(1);
link.Add(2);
link.Add(3);
MyArray<float>::ArrayIterator aryStart(ary.Begin());
MyArray<float>::ArrayIterator aryEnd(ary.End());
MyLink<int>::LinkIterator linkStart(link.Begin());
MyLink<int>::LinkIterator linkEnd(link.End());
Display(aryStart,aryEnd);
Display(linkStart,linkEnd);
return 0;
}注意!上述代码我在 VS 2010 下编译正确,运行正确,但在 CodeBlocks 用 GNU GCC 编译器编译时报错,难道是 GCC 编译器的bug?希望有知道的大神赐教。#include <iostream>
#include <iterator>
using namespace std;
int main()
{
cout<<"请输入数据(如1 2 3,):";
istream_iterator<int> Start(cin); //建立键盘输入流
istream_iterator<int> End; //建立输入流结束迭代器
while(1)
{
cout<<*Start<<endl;
Start++;
if(Start==End)
break;
}
return 0;
}
程序执行结果为:
#include <iostream>
#include <iterator>
using namespace std;
int main()
{
ostream_iterator<int> Out(cout,"\t");
*Out=1;
Out++;
*Out=2;
Out++;
*Out=3;
Out++;
return 0;
}程序执行结果为:template <class ForwardIterator,class T>
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 本事并没有专门为前向迭代器预定义的迭代器。标签:
原文地址:http://blog.csdn.net/raito__/article/details/51494599