简介
在C开发,是一个必须有:它已被视为可能的,抽象的,通用性,和可扩展的简单。其中一个重要的通用概念,STL的C开发人员熟悉的是迭代器的概念。
迭代器是用于访问容器中的元素没有露出容器是如何实现(例如,一个向量,列表,红黑树,哈希集合,队列等)。迭代器是通用编程的核心,因为他们是一个容器和应用程序之间的接口。应用程序需要访问容器中的元素,但它们通常并不需要知道如何在容器中的元素。迭代器使得它可以编写泛型算法,对不同类型的容器操作。
例如,下面的代码片段公开容器的性质 - 一个载体。void process(const std::vector<E>& v)
{
for (unsigned i = 0; i < v.size(); ++i) {
process(v[i]);
}
}
如果我们要对列表中的相同功能的操作,我们写一个单独的函数。或者,如果我们后来决定,列表或散列设置是作为一个容器更合适,我们需要重写代码,我们到处访问的载体。这可能需要很多的变化在许多文件。这个容器进行对比,具体探视以下计划:{C}
使用迭代器的概念,我们有一个容器"C"的通用处理,无论是一个向量,列表,哈希集合,或任何数据结构,在它的API提供的迭代器的。更妙的是,我们可以写一个通用的进程的功能,只需要一个迭代的范围内,不承担责任,容器都有一个开始()和end()方法:template <typename Iterator>
void process(Iterator begin, Iterator end)
{
for (; itr != end; ++itr) {
process(*itr);
}
}
一个STL迭代器是一种商品,作为一个标量类型的行为:它可以在堆上分配它可以被复制它可以通过值传递它可以被分配到
迭代器的本质是捕获以下API:template <typename T>
class Itr {
public:
Itr();
Itr();
Itr(const Itr& o); // Copy constructor
Itr& operator=(const Itr& o); // Assignment operator
Itr& operator++(); // Next element
T& operator*(); // Dereference
bool operator==(const Itr& o) const; // Comparison
bool operator!=(const Itr& o) const { return !(*this == o); }
}
通常情况下,容器将提供一个begin()和结束()方法,该方法构建的迭代器,表示容器的范围。如果容器是从一个STL容器派生这些方法开始/结束的写作是一件容易的事,如果容器有一个数据成员,是一个STL容器,或迭代器,如果是标量类型,像一个指针或索引。
这是更复杂,如果我们想取消引用同一类型的对象,但必须访问多个容器,可能的不同类型,或以不同的方式访问容器的迭代器迭代器。例如,让我们假设我们有一些属性(例如,颜色)存储在多个货柜,其中有一些不同类型的对象。我们想访问的所有对象,独立的容器和它们的类型的数量,或者我们想访问一个给定的颜色的对象,或者我们想访问的对象,满足一些谓词:Itr<E> begin(); // This give the range to visit
Itr<E> end(); // all the elements of type E
Itr<E> begin(const Color& color); // Same as above but only for the
Itr<E> end(const Coir& color); // elements of the given color
class Predicate {
public:
bool operator()(const E& e);
};
Itr<E> begin(Predicate& p); // Same as above but only for the
Itr<E> end(Predicate& p); // elements that satisfy the predicate
在这种情况下,迭代器是多像一个指针或索引的标量类型复杂:它需要跟踪,其中容器,它是目前访问,或需要检查它的颜色或谓词。在一般情况下,迭代可能有数据成员,以便它能够履行其任务。同时,我们要因式分解的代码和重用通用的迭代方法,写作时更有针对性的迭代器,例如,访问一个特定的颜色元素,要使用的下一个元素的方法Itrlt; EGT;::operator()的。这是可以做到有Itrlt; EGT;是一个虚拟的类,派生类来实现不同的迭代器。例如:class E {
public:
Color& color() const;
};
template <typename E>
class ColoredItr<E> : public Itr<E> {
private:
typedef Itr<E> _Super;
public:
ColoredItr<E>(const Color& color) : Itr<E>(), color_(color) {}
virtual ColoredItr<E>;
virtual ColoredItr<E>& Operator++() {
for (; _Super::operator*().color() != color_; _Super::operator++());
return *this;
}
private:
Color color_;
};
我们想一个通用的迭代器,以满足上述所有要求:它可以在堆上分配它可以被复制它可以通过值传递它可以被分配到它取消引用同一类型它可以访问多个容器它可以访问不同类型的容器它可以在任意礼仪访问的容器
这可以实现如下:template<typename E>
class ItrBase {
public:
ItrBase() {}
virtual ItrBase() {}
virtual void operator++() {}
virtual E& operator*() const { return E(); }
virtual ItrBase* clone() const { return new ItrBase(*this); }
// The == operator is non-virtual. It checks that the
// derived objects have compatible types, then calls the
// virtual comparison function equal.
bool operator==(const ItrBase& o) const {
return typeid(*this) == typeid(o) && equal(o);
}
protected:
virtual bool equal(const ItrBase& o) const { return true; }
};
template<typename E>
class Itr {
public:
Itr() : itr_(0) {}
Itr() { delete itr_; }
Itr(const Itr& o) : itr_(o.itr_->clone()) {}
Itr& operator=(const Itr& o) {
delete itr_; itr_ = o.itr_->clone(); return *this;
}
Itr& operator++() { ++(*itr_); return *this; }
E& operator*() const { return *(*itr_); }
bool operator==(const Itr& o) const {
return (itr_ == o.itr_) || (*itr_ == *o.itr_);
}
bool operator!=(const Itr& o) const { return !(*this == o); }
protected:
ItrBase<E>* itr_;
};
ItrBase类的类层次结构的顶层。 ITR是简单的包装上一个ItrBase指针,所以它可以在堆上分配 - 实际执行ItrBase派生类可以有一个任意大小的。注意ITR复制和赋值操作符如何通过ItrBase实施:clone()方法,使ITR作为一个标量类型的行为。最后但并非最不重要,(非虚拟)ItrBase::操作符==等于运算符类型,然后调用(虚拟)平等方法对虚拟子类的平等平等首先检查。 ItrBase不是一个纯虚的原因是,它可以很方便地用来表示一个空的范围,即,范围(ItrBase(),ItrBase())是空的。
E型元素的容器迭代只需要从ItrBaselt; EGT,及工厂提供的begin()和end()方法;任何专门的迭代器返回对象类型Itrlt EGT;
例如,让我们假设我们有一个ES的容器C,以及我们想要一个iterator访问:所有的元素C,可能与重复;所有的元素,没有重复的C。
这是可以做到如下: