标签:
(比上一章节的数组类仅多了 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