Autumn SALE
Итератор

Итератор на C++

Итератор — это поведенческий паттерн, позволяющий последовательно обходить сложную коллекцию, без раскрытия деталей её реализации.

Благодаря Итератору, клиент может обходить разные коллекции одним и тем же способом, используя единый интерфейс итераторов.

Сложность:

Популярность:

Применимость: Паттерн можно часто встретить в C++ коде, особенно в программах, работающих с разными типами коллекций, и где требуется обход разных сущностей.

Признаки применения паттерна: Итератор легко определить по методам навигации (например, получения следующего/предыдущего элемента и т. д.). Код использующий итератор зачастую вообще не имеет ссылок на коллекцию, с которой работает итератор. Итератор либо принимает коллекцию в параметрах конструктора при создании, либо возвращается самой коллекцией.

Концептуальный пример

Этот пример показывает структуру паттерна Итератор, а именно — из каких классов он состоит, какие роли эти классы выполняют и как они взаимодействуют друг с другом.

main.cc: Пример структуры паттерна

/** * Паттерн Итератор * * Назначение: Даёт возможность последовательно обходить элементы составных * объектов, не раскрывая их внутреннего представления. */ #include <iostream> #include <string> #include <vector> /** * C++ has its own implementation of iterator that works with a different * generics containers defined by the standard library. */ template <typename T, typename U> class Iterator { public: typedef typename std::vector<T>::iterator iter_type; Iterator(U *p_data, bool reverse = false) : m_p_data_(p_data) { m_it_ = m_p_data_->m_data_.begin(); } void First() { m_it_ = m_p_data_->m_data_.begin(); } void Next() { m_it_++; } bool IsDone() { return (m_it_ == m_p_data_->m_data_.end()); } iter_type Current() { return m_it_; } private: U *m_p_data_; iter_type m_it_; }; /** * Конкретные Коллекции предоставляют один или несколько методов для получения * новых экземпляров итератора, совместимых с классом коллекции. */ template <class T> class Container { friend class Iterator<T, Container>; public: void Add(T a) { m_data_.push_back(a); } Iterator<T, Container> *CreateIterator() { return new Iterator<T, Container>(this); } private: std::vector<T> m_data_; }; class Data { public: Data(int a = 0) : m_data_(a) {} void set_data(int a) { m_data_ = a; } int data() { return m_data_; } private: int m_data_; }; /** * The client code may or may not know about the Concrete Iterator or Collection * classes, for this implementation the container is generic so you can used * with an int or with a custom class. */ void ClientCode() { std::cout << "________________Iterator with int______________________________________" << std::endl; Container<int> cont; for (int i = 0; i < 10; i++) { cont.Add(i); } Iterator<int, Container<int>> *it = cont.CreateIterator(); for (it->First(); !it->IsDone(); it->Next()) { std::cout << *it->Current() << std::endl; } Container<Data> cont2; Data a(100), b(1000), c(10000); cont2.Add(a); cont2.Add(b); cont2.Add(c); std::cout << "________________Iterator with custom Class______________________________" << std::endl; Iterator<Data, Container<Data>> *it2 = cont2.CreateIterator(); for (it2->First(); !it2->IsDone(); it2->Next()) { std::cout << it2->Current()->data() << std::endl; } delete it; delete it2; } int main() { ClientCode(); return 0; } 

Output.txt: Результат выполнения

________________Iterator with int______________________________________ 0 1 2 3 4 5 6 7 8 9 ________________Iterator with custom Class______________________________ 100 1000 10000 

Итератор на других языках программирования

Итератор на C# Итератор на Go Итератор на Java Итератор на PHP Итератор на Python Итератор на Ruby Итератор на Rust Итератор на Swift Итератор на TypeScript