迭代器模式,即提供一种方法顺序的访问一个集合对象中的各个元素。而又不暴露其内部的表示。那么为什么需要这样设计呢?让我们考虑如下情况。
我们CString有两个不同版本的实现,然后当我们需要访问其各个元素时,却不得依据其集合的表达方式写出对应的访问。也就是说我们其实是在依赖于实现编程了。当有其他的实现版本的时候,我们访问各个元素的方式还得改变。因此迭代器应运而生,提供一套与实现无关的访问元素接口。
#include <stdio.h>
#include <string.h>
#include <vector>
#include <string>
class CString
{
public:
CString(): m_str(NULL), m_strlen(0){}
CString(const char *str)
{
m_str = strdup(str);
m_strlen = strlen(str);
}
~CString()
{
if(m_str != NULL)
delete m_str;
}
const char *members() const
{
return m_str;
}
private:
char *m_str;
std::size_t m_strlen;
};
int main(int argc, char **argv)
{
CString str("iterator pattern");
const char *member = str.members();
printf("%s\n", member);
return 0;
}
#include <stdio.h>
#include <string.h>
#include <vector>
#include <string>
class CString
{
public:
CString(){}
CString(const char *str): m_str(str, str + strlen(str)){}
~CString(){}
const std::vector<char> &members() const
{
return m_str;
}
private:
std::vector<char> m_str;
};
int main(int argc, char *argv[])
{
CString str("iterator pattern");
const std::vector<char> &strmember = str.members();
std::vector<char>::const_iterator it = strmember.begin();
for(; it != strmember.end(); it++)
printf("%c", *it);
printf("\n");
return 0;
}
让我们编写迭代器首先我们需要重载前置++与--,提供迭代器的移动。同时我们需要重载后置++与--运算符,提供一个int参数与前置作为区分,无实际用处;后置版本需要先保存一份旧的对象,移动指针后,返回旧的对象,因此返回的也不能是引用。
然后我们需要重载==与!=,以及<,<=, >, >=运算符。提供迭代器控制循环遍历的能力,判断是否到达结尾等。统一都是返回bool类型的判断结果。
由于我们需要通过迭代器访问元素,因此我们需要重载*, ->, [ ] 运算符。我们给CString编写个begin与end接口,返回开始迭代器与结尾迭代器。这样就可以通过迭代器遍历元素了。
#include <stdio.h>
#include <string.h>
#include <string>
template <typename Value>
class IteratorBase
{
friend class CString;
public:
typedef Value *ValuePointer;
typedef Value &ValueReference;
typedef std::ptrdiff_t DiffType;
public:
virtual ~IteratorBase(){};
IteratorBase(): valptr(){}
IteratorBase(const IteratorBase &itor): valptr(itor.valptr){}
IteratorBase &operator =(const IteratorBase &itor)
{
valptr = itor.valptr;
return *this;
}
IteratorBase &operator ++()
{
++valptr;
return *this;
}
IteratorBase &operator --()
{
--valptr;
return *this;
}
IteratorBase operator ++(int)
{
IteratorBase old(*this);
++valptr;
return old;
}
IteratorBase operator --(int)
{
IteratorBase old(*this);
--valptr;
return old;
}
IteratorBase operator +(DiffType n) const
{
return IteratorBase(valptr + n);
}
IteratorBase operator -(DiffType n) const
{
return IteratorBase(valptr - n);
}
IteratorBase &operator +=(DiffType n)
{
valptr += n;
return *this;
}
IteratorBase &operator -=(DiffType n)
{
valptr -= n;
return *this;
}
bool operator ==(const IteratorBase &itor) const
{
return (valptr == itor.valptr);
}
bool operator !=(const IteratorBase &itor) const
{
return (valptr != itor.valptr);
}
bool operator <(const IteratorBase &itor) const
{
return (valptr < itor.valptr);
}
bool operator <=(const IteratorBase &itor) const
{
return (valptr <= itor.valptr);
}
bool operator >(const IteratorBase &itor) const
{
return (valptr > itor.valptr);
}
bool operator >=(const IteratorBase &itor) const
{
return (valptr >= itor.valptr);
}
ValueReference operator *() const
{
return *valptr;
}
ValuePointer operator ->() const
{
return valptr;
}
Value operator [](DiffType idx) const
{
return valptr[idx];
}
private:
explicit IteratorBase(ValuePointer ptr): valptr(ptr){};
private:
ValuePointer valptr;
};
class CString
{
public:
typedef IteratorBase<char> Iterator;
public:
CString(): valptr(NULL), valptrlen(0){}
explicit CString(const CString &cstr): valptr(NULL), valptrlen(0)
{
if(cstr.valptr != NULL){
valptrlen = cstr.valptrlen;
valptr = strdup(cstr.valptr);
}
}
explicit CString(const char *str)
{
valptrlen = strlen(str);
valptr = strdup(str);
}
~CString()
{
if(valptr != NULL){
delete valptr;
valptrlen = 0x00;
}
}
Iterator begin() const
{
return Iterator(valptr);
}
Iterator end() const
{
return Iterator(valptr + valptrlen);
}
private:
char *valptr;
std::size_t valptrlen;
};
int main(int argc, char **argv)
{
CString str("iterator pattern");
CString::Iterator itor = str.begin();
for(; itor != str.end(); itor++){
printf("%c", *itor);
}
printf("\n");
return 0;
}