2010-04-16 63 views
12

我目前正在尝试理解各种语言中迭代器的内在性,即它们实现的方式。在C++中编写我自己的stl-like迭代器实现

例如,有以下类暴露列表界面。

template<class T> 
class List 
{ 

    public: 

    virtual void Insert(int beforeIndex, const T item) throw(ListException) =0 ; 
    virtual void Append(const T item) =0; 

    virtual T Get(int position) const throw(ListException) =0; 
    virtual int GetLength() const =0; 

    virtual void Remove(int position) throw(ListException) =0; 


    virtual ~List() =0 {}; 
}; 

根据四人帮,实现能够支持不同类型的遍历的迭代器的最佳方式是创建基本的迭代器类(列表的朋友)与可访问列表的成员保护的方法。 Iterator的具体实现将以不同的方式处理作业,并通过基本接口访问List的私有和受保护数据。

从这里开始,事情变得混乱。说,我有类LinkedList和ArrayList,都从List派生,并且还有相应的迭代器,每个类都返回。我怎样才能实现LinkedListIterator?我完全没有想法。基类迭代器类可以从列表中检索什么样的数据(这是一个纯粹的接口,而所有派生类的实现差别很大)?

+3

Boost迭代器库是一个很好的信息来源,并且开发了新的迭代器类型/特性http://www.boost.org/doc/libs/1_42_0/libs/iterator/doc/index.html – Hippicoder 2010-04-16 22:26:32

+1

这种气味如Java/C#代码。通常,好的C++看起来不像Java或C#。 – 2010-04-16 22:51:39

+0

为什么你想从'List'派生,如果它是模板化的?如果删除所有'虚拟'限定符并提供缺少的定义,则可以将其用于任何可想到的目的。 – wilhelmtell 2010-04-17 02:27:31

回答

14

STL并没有真正使用抽象基类和虚函数。相反,它被有意设计成不是OO(在GoF意义上)并且完全基于模板,旨在“编译时多态性”。模板不关心抽象接口。只要它们具有足够类似的接口(例如,如果您打电话给Appendpush_back而不是更多的代码,期望符合STL的容器可以为您工作,如std::back_insert_iterator)。

一个兼容STL的迭代器将不得不超负荷很多运营商的表现就像一个指针(尽可能,考虑到容器的限制),包括*->++--(如果双向 - 双链接), ==!=

+2

并注意'++'和'--'分别是两个不同的运算符。如果你正在实现的迭代器类型需要一个'++',那么它们都是,而'--'也是一样的。 – 2010-04-16 23:04:08

7

C++标准库在迭代器的实现中不使用多态和继承;相反,它使用C++模板元编程和“概念”的概念(但不是形式语法*)。

从本质上讲,如果您的迭代器类的接口符合一些要求,它将会工作。这套要求被称为“概念”。有几种不同的迭代器概念(参见this page for a list of all of them),它们是分层的。创建一个兼容的C++迭代器的基础是让你的接口符合这个概念。对于一个简单的迭代器,也仅限于前进方向,这将需要:

  • 一种从提领你的迭代所得的值的typedef value_type
  • A typedef reference_type,它是相应值类型的参考类型。
  • A typedef pointer,它是相应值类型的指针类型。
  • typedef iterator_category,根据您的遍历机制,它需要是input_iterator_tag,forward_iterator_tag,bidirectional_iterator_tag或random_access_iterator_tag之一。
  • A typedef difference_type指示减去两个不同迭代器的结果。
  • A const value_type& operator*()const取消引用迭代器的函数。
  • A value_type& operator*()函数,如果你的迭代器可以用来操纵值。
  • 递增(operator++()operator++(int)功能)寻求前进。
  • 的不同功能:difference_type operator-(const type_of_iterator&)

如果你选择了更先进的迭代器类别之一,你可能还需要以指定递减,并且加上运营商能够寻求向后或寻求的任意距离。

* C++标准库以非正式方式频繁使用概念,C++标准委员会试图引入一种用C++声明它们的正式机制(目前它们只存在于标准库的文档中,而不存在于任何显式代码)。然而,对于该提案的持续不同意见导致其被C++ 0x取消,不过之后它很可能会重新考虑该标准。

+2

typedefs不是迭代器类型的要求,但是'iterator_traits'的合适的特殊性是。使用'iterator'模板和一个迭代器类型标记来安排这种智能的方法,而不是通过显式定义typedef。另外,前向迭代器不需要'operator-',(直到RandomAccess才需要),但是需要'=='和'!='表达式。迭代器不需要'reference_type'和'pointer',但默认的'iterator_traits'模板需要它们。我不知道这是为什么。 – 2010-04-16 23:16:30

+0

@Steve:C++ 0x确实需要'reference'和'pointer'。 – Potatoswatter 2010-04-17 05:39:17

+0

@Steve,这是正确的......它确实说在我链接的文档中,但我想保持简单;换句话说,我的指示是足够的,但不是必要的。 – 2010-04-18 01:37:46