The process of going through a data structure and accessing each element of the structure is called iterating over the data structure (like traversing an array).
We could use the list “head” pointer to access the first element, and then continue through the list by using “getnext”. The problem is that the implementation of the list - and the list “head” in particular - is private and thus we cannot access it from outside the List class.
Provide a get_head function in the List class, which would return the value of the private list header data member. The problem with this approach, of course, is that it violates the principle of data hiding. Once we provide access to the list header, we are providing access to the internal workings of the list. Secondly, the application program must be aware of, and responsible for working with, any variation in the list organization (e.g. header nodes, circular lists, doubly lists). In fact, the application program should not even be aware of the existence of nodes (theoretically, a list could be implemented using an array).
Define a second class, called an iterator. This iterator class is defined to be a friend of the original class (the list class), which means that it has full access to all the members of the original class. The iterator class will provide methods, which can be used to traverse the original class, e.g.
class List{
friend
class ListIter; // add
this to the class List definition
public:
.
.
.
.
private:
.
.
.
.
};
(the method firstnode() or any variation of it should not be included in the public part of class List)
//ListIter.h//header file for class ListIter #ifndef ITER_H#define ITER_H #include "List.h" class ListIter { public: ListIter(List &); void next(); Type lookup(); int done(); private: Node *current;}; #endif
The List Iterator class provides a constructor, which
initializes the internal pointer of the class to the beginning of the list. The
other methods provide the means of advancing the pointer, retrieving the
information stored in the current element of the list, and testing for the end
of the iteration.
//ListIter.cpp //methods for class ListIter #include "ListIter.h" ListIter::ListIter(List &l) { // a reference must be passed to the current = l.head; // constructor, if not the destructor will
} // destroy the original list.
void ListIter::next() { assert(current); current = current->getnext();} Type ListIter::lookup() { assert (current); return(current->getinfo()); } int ListIter::done() { return current==0;}
//TListIter.cpp //test driver for class ListIter #include "ListIter.h"
main() { List L; ListIter iter(L); for (int i = 0; i < 20; i++) L.insertfront(i); // while loop example count = 0; while(!iter.done()) { count++; cout << iter.lookup() << ' '; iter.next(); }