前述のリストのようなクラスの場合,繰り返しを実現するために, nextなどのメンバ変数を参照しなければならない.
これをやるにはnextをpublicにしなければならないが,それは あまり好まれないので,代わりにnextの内容を返す関数を 作ったりする.List<int> *p; .... for (List<int> *q = p; q != NULL; q = q->next) { 処理 }
しかし,これでもList<T>の内部構造が見えすぎる感じがする. そこで,こんなことをする場合がある.template <class T> class List { protected: List<T> *next; public: .... List<T> *next_item() { return next; } }; List<int> *p; .... for (List<int> *q = p; q != NULL; q = q->next_item()) { 処理 }
ListIter<T>というクラスでは,++と*を 再定義している.このListIter<T>を使うと,List に関する繰り返しは,こんな形で書ける.template <class T> class List { friend class ListIter<T>; protected: List<T> *next; public: .... }; template <class T> class ListIter { protected: List<T>* list; public: ListIter<T>(List<T>* p) { list = p; } int null() { return list == 0; } void operator ++ () { if (list) list = list->next; } T& operator *() { return list->nakami; } };
ListIterは,Listに関する繰り返しを封じ込めたクラスだ. これを使えば,配列に関する繰り返しのような感覚で,Listに ついての繰り返しを記述することができる.こういうクラスをイテレータクラス と呼ぶ.イテレータクラスを定義しておけば,それが指しているクラスの実装が 連結リストか配列か...ということを全く気にしなくてよくなる.List<int> *p; ... for (ListIter<int> i(p); !i.null(); ++i) { printf("%d¥n",*i); }