Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Lutsik_Yu_A_Obektno_orientir_programmir_na_yaz.pdf
Скачиваний:
64
Добавлен:
11.05.2015
Размер:
4.33 Mб
Скачать

щие во второе;

set_intersection – противоположный предыдущему алгоритму; set_symmetric_difference – выделяются элементы, которые содержатся

только в одном из двух множеств;

set_union – объединение двух множеств в одно.

9.8.7. Алгоритмы swap, iter_swap и swap_ranges

Данная группа алгоритмов предназначена для выполнения перестановки

элементов контейнера. Ниже приведены прототипы данных алгоритмов:

Р

template<class T, class A>

 

void swap(const vector <T, A>& lhs,const vector <T, A>& rhs);

Аргументами алгоритма swap являются ссылки на элементы для замены

template<class FwdIt1, class FwdIt2>

У

void iter_swap(FwdIt1 x, FwdIt2 y);

 

Г

 

Аргументами алгоритма являются два прямых итератора на элементыИ. template<class FwdIt1, class FwdIt2>

FwdIt2 swap_ranges(FwdIt1 first, FwdIt1 last, FwdIt2 x);

алгоритм swap_ranges используется для перестановки элементов от first до last с

элементами начиная с х.

 

а

Все указанные замены производятся в одном иБтом же контейнере.

 

к

 

е

 

9.8.8. Алгоритмы copy, copy_backward, merge, unique и reverse

Дадим краткую характеристику алгоритмам опирования:

тора в другой;

merge – используетсяодля бъединения двух отсортированных последова- тельностей в третью;

copy_backward – используется для копирования элементов из одного век-

9.9. Пассивныебиктиа вные итераторы

unique – исключает дубл рование элементов в последовательности;

reverse – используелся для перебора элементов в обратном порядке.

объекты, ответственные за итеративный опрос других структур. К достоинствам второгоБподхода относятся:

Можнолиопреде ять итерацию как часть объекта или создавать отдельные

- на чие выделенного итератора классов, позволяющего одновременно проводить несколько просмотров одного и того же объекта;

- наличие итерационного механизма в самом классе, что несколько нару- шает его инкапсуляцию; выделение итератора в качестве отдельного механизма поведения, что способствует достижению большей ясности в описании класса.

Для каждой структуры определены две формы итераций. Активный ите-

ратор требует каждый раз от клиента явного обращения к себе для перехода к следующему элементу. Пассивный итератор применяет функцию, предостав- ляемую клиентом, и, таким образом, требует меньшего вмешательства клиента.

226

С целью обеспечения безопасности типов для каждой структуры создаются свои итераторы.

Ниже приведен пример использования активного итератора.

// --------------- реализация

aktiv_itr.h файла -------------

#include <iostream>

 

 

 

#include <vector>

 

 

 

#include <string>

 

 

 

using namespace std;

 

 

Р

class Node

 

 

 

 

 

{

string name;

 

И

public:

 

 

 

 

 

Node(string s) : name(s) {}

У

 

 

Node() {}

 

 

string getName() const

 

};

{ return name;}

 

class NodeCollection

БГ

 

 

{vector<Node> vec; int index;

 

 

 

 

 

 

а

 

public:

 

 

к

 

 

NodeCollection() : index(0) {}

 

 

 

void addNode(Node);

 

 

 

 

 

 

 

т

 

 

 

 

 

Node getNode(int) const;

 

 

 

 

int getIndex() const;е//возвращает индекс последнего элемента

 

};

 

о

 

 

 

 

 

 

 

 

 

 

 

class Iterator

 

 

 

// интерфейс итератора

 

{

л

 

 

 

 

 

 

public:

 

 

 

 

 

 

б

 

 

 

 

 

 

 

virtualиNode next() = 0;

 

 

 

и

virtual bool isDone() const = 0;

 

virtual ~Iterator() { }

 

 

 

 

};

 

 

 

Б

 

 

 

 

 

 

class ActiveIterator : public Iterator // реализация итератора

 

 

{ NodeCollection collection;

 

 

 

 

int currentIndex;

 

 

// текущий индекс

 

public:

 

 

 

 

 

ActiveIterator(const NodeCollection&); Node next();

bool isDone() const; virtual ~ActiveIterator() { }

};

227

// ----------------

реализация aktiv_itr.cpp файла

---------------

#include "aktiv_itr.h"

 

void NodeCollection::addNode(Node n)

 

{ vec.push_back(n);

 

index++;

 

 

}

 

 

Node NodeCollection::getNode(int i) const

Р

{ return vec[i];

}

 

int NodeCollection::getIndex() const

И

{ return index;

}

ActiveIterator::ActiveIterator(const NodeCollection& c)

{collection = c;

 

 

 

 

 

 

 

 

 

 

 

У

 

currentIndex = 0;

 

 

 

 

 

Г

}

 

 

 

 

 

 

 

 

 

Б

 

Node ActiveIterator::next()

 

 

 

 

 

{

return(collection.getNode(currentIndex++));

}

 

bool ActiveIterator::isDone() const

к

 

 

{

if(collection.getIndex() > currentIndex)

 

 

 

}

 

 

 

 

 

 

е

 

 

 

 

return false;

 

 

 

// продолжениеаитерации

 

else

 

 

 

 

т

 

 

 

 

 

return true;

 

о

// ит рация завершена

 

int main()

 

 

 

 

 

 

 

 

и

 

 

 

 

 

 

{

 

 

 

 

 

 

 

 

 

NodeCollection c;

 

 

 

 

 

 

 

 

c.addNode(Node("first"));

 

 

 

 

 

 

 

 

л

 

 

 

 

 

 

 

 

c.addNode(Node("second"));

 

 

 

 

 

 

 

б

 

 

 

 

 

 

 

 

 

c.addNode(Node("third"));

 

 

 

 

 

 

Iterator* pI = new ActiveIterator(c); //инициализируем итератор

 

Node n;

 

 

 

 

 

 

 

 

 

 

while(!pI->isDone())

 

 

 

 

 

 

Б

 

 

 

 

 

 

 

 

 

 

 

{ n = pI->next();

 

 

 

 

 

 

 

 

иcout << n.getName() << endl;

 

 

 

 

}

delete pI; return 0;

}

Результат работы программы: first

second

228

third

Каждому итератору ставится в соответствие определенный объект. Пере- ход к следующему элементу последовательности выполняется функцией next(), возвращающей 0, если итерация завершена. Функция isDone() проверяет при- надлежность текущего индекса допустимому диапазону и возвращает информа- цию о состоянии процесса (true − если итерация завершена, иначе false).

Конструктор класса ActiveIterator сначала устанавливает связь между ите- ратором и конкретным объектом. Затем текущий индекс устанавливается рав- ным 0.

Класс итератора абстрактный класс с отложенной реализацией методов next и isDone. Конкретная реализация их передана классу, производному от

Iterator.

 

 

 

 

 

 

 

Пассивный итератор, который также называют аппликаторомР, характери-

 

 

 

 

 

 

 

У

зуется тем, что он применяет определенную функцию к каждому элементу

 

 

 

 

 

 

Г

структуры. Для класса Queue пассивный итератор можноИопределить следую-

щим образом:

 

 

 

 

 

 

template <class Item>

 

 

 

 

class PassiveIterator

 

 

а

 

 

{public:

 

 

 

 

 

 

PassiveIterator(const Queue<Item>&);Б

 

 

~PassiveIterator();

к

 

 

};

 

 

 

е

 

 

 

 

int apply(int (*) (const Item&));

 

 

protected:

 

 

 

 

 

 

 

const Queue<Item>& queue;

 

 

 

 

 

о

 

 

 

 

Пассивный итера ор дейс вует на все элементы структуры за (логически)

одну операцию. Таким

бразом, функция apply() последовательно производит

 

и

 

 

 

 

 

одну и ту же операц ютнад каждым элементом структуры, пока передаваемая

 

л

 

 

 

 

 

 

итератору функц я не в звратит нулевое значение или пока не будет достигнут

конец структуры. В первом случае функция apply() сама возвратит нулевое зна-

 

б

чение в знак того, что итерация не была завершена.

и

Б

Упражнения для закрепления материала

1. Разработать контейнерный класс vect, в классе реализовать некоторые

 

методы, аналогичные методам класса vector из STL.

2. Разработать контейнерный класс list, в классе реализовать некоторые методы, аналогичные методам класса list из STL.

3. Для ассоциативного контейнерного класса multimap (map) выполнить перегрузку операции сравнения.

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

229

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]