我目前正在尝试理解各种语言的迭代器的内在函数,即它们的实现方式。
例如,有以下类公开列表界面。
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 {};
};
根据 GoF ,实现可以支持不同类型遍历的迭代器的最佳方法是使用可以访问List成员的受保护方法创建基类Iterator类(List的朋友)。 Iterator的具体实现将以不同的方式处理作业,并通过基接口访问List的私有和受保护数据。
从这里开始,事情变得令人困惑。说,我有类LinkedList和ArrayList,都是从List派生的,并且还有相应的迭代器,每个类都返回。我该如何实现LinkedListIterator?我完全没有想法。基础迭代器类可以从List中检索哪种数据(这只是一个接口,而所有派生类的实现差异很大)?
答案 0 :(得分:14)
STL并没有真正使用抽象基类和虚函数。相反,它被明智地设计为不是OO(在GoF意义上)并且完全基于模板构建,旨在“编译时多态性”。模板不关心抽象接口。只要它们具有足够相似的界面(例如,如果您要调用Append
push_back
,那么事情就会起作用,更多代码期望符合STL的容器对您有用,例如std::back_insert_iterator
)。
符合STL标准的迭代器必须使许多运算符超载,使其表现得像指针(尽可能,考虑到容器的限制),包括*
,->
,{{1} },++
(如果双向 - 双重关联),--
和==
。
答案 1 :(得分:7)
C ++标准库在迭代器的实现中不使用多态和继承;相反,它使用C ++模板元编程和“概念”的概念(但不是形式语法*)。
基本上,如果迭代器类的接口遵循某些要求,它将起作用。这组要求称为“概念”。有几种不同的迭代器概念(参见this page for a list of all of them),它们是分层的。创建兼容的C ++迭代器的基础是使您的接口符合该概念。对于仅向前移动的简单迭代器,这需要:
value_type
,用于取消引用迭代器所产生的值。reference_type
,它是相应值类型的引用类型。pointer
,它是相应值类型的指针类型。iterator_category
,需要是input_iterator_tag,forward_iterator_tag,bidirectional_iterator_tag或random_access_iterator_tag之一,具体取决于您的遍历机制。difference_type
,指示减去两个不同迭代器的结果。const value_type& operator*()const
函数。value_type& operator*()
函数。operator++()
和operator++(int)
函数)以寻求前瞻。difference_type operator-(const type_of_iterator&)
如果您选择一个更高级的迭代器类别,您可能还需要指定一个减量和加号运算符,以便能够向后搜索或寻找任意距离。
* C ++标准库以非正式的方式经常使用概念,C ++标准委员会试图引入一种在C ++中声明它们的正式机制(目前它们只存在于标准库的文档中,而不是任何显式的码)。但是,对该提案的持续不同意见导致它被废弃为C ++ 0x,尽管之后很可能会重新考虑该标准。