Итератор за класа List
За обхождане на елементите на класа List ще дефинираме помощен клас iterator. За да може нашият итератор да имитира итераторите от стандартната библиотека е необходимо да се владеят механизмите за предефиниране на оператори. Поради това на този етап итератора, който ще дефинираме няма да разполага с обичайните за C++ механизми.
[note]
Итераторите са често използван design pattern. Класическият източник за запознаване с общите принципи на този design pattern е:
Други полезни източници са:
- Head First Design Patterns
- Portland Pattern Repository’s Wiki: Iterator Pattern
- Wikipedia: Iterator Pattern
[/note]
Класът итератор за класа List е тясно свързан с вътрешното устройство на контейнера List. Поради това дефинираме класа iterator като вътрешен клас на класа List. Освен това ще направим класа List приятелски клас на класа iterator:
class List {
...
public:
...
class iterator {
friend class List;
List* list_;
Node* current_;
iterator(const List* l,Node* current)
: list_(const_cast<List*>(l)),
current_(current)
{}
public:
...
};
...
};
Като член-променливи на класа iterator дефинираме:
const List *const list_– указател към списъка, който ще обхождаме с помощта на итератора;Node* current_– указател към елемента на списъка, към който е насочен итератора.
Конструктора е дефиниран в private частта на класа. Това гарантира, че обекти от типа List::iterator могат да се създават само от членовете на самият клас и неговите приятели (в случая класа List). Конструктора на iterator инициализира член-променливите на класа.
class List {
...
public:
...
class iterator {
...
public:
bool has_next() const {
return current_->next_!=list_->head_;
}
int next() {
current_=current_->next_;
return current_->data_;
}
int get_data() const {
if(current_!=list_->head_) {
return current_->data_;
}
throw ListError("iterator::get_data()...");
}
};
...
};
Методите на класа iterator имитират начина на работа на итераторите в Java.
has_next()– проверява дали итератора е стигнал до края на списъка. Ако итератора е позициониран върху последният елемент на списъка, тоhas_next()връщаfalse, иначе връщаtrue.next()– извършва едновременно две операции – позиционира итератора върху следващият елемент на списъка и връща стойността на елемента, върху който е позициониран.get_data()– връща стойността на елемента, върху който е позициониран итератора. Ако итератора е позициониран върху фиктивният елемент, то този метод генерира изключениеListError().
