
- •Учебное пособие
- •Введение
- •Объектно-ориентированный подход
- •Объектно-ориентированное программирование Абстрактные типы данных
- •Базовые принципы объектно-ориентированного программирования
- •Простейший ввод и вывод
- •Объект cout
- •Манипуляторы hex и oct
- •Другие манипуляторы
- •Объект cin
- •Операторы для динамического выделения и освобождения памяти (new и delete)
- •Базовые конструкции объектно-ориентированных программ Объекты
- •Понятие класса
- •Конструктор копирования
- •Конструктор explicit
- •Указатели на компоненты класса
- •Встроенные функции (спецификатор inline)
- •Организация внешнего доступа к локальным компонентам класса (спецификатор friend)
- •Вложенные классы
- •Static-члены (данные) класса
- •Указатель this
- •Компоненты-функции static и const
- •Proxi-классы
- •Параметры ссылки
- •Независимые ссылки
- •Практические приемы ограничения числа объектов класса
- •Наследование (производные классы)
- •Конструкторы и деструкторы при наследовании
- •Виртуальные функции
- •Абстрактные классы
- •Виртуальные деструкторы
- •Множественное наследование
- •Виртуальное наследование
- •Перегрузка функций
- •Перегрузка операторов
- •Перегрузка бинарного оператора
- •Перегрузка унарного оператора
- •Дружественная функция operator
- •Перегрузка оператора []
- •Перегрузка оператора ()
- •Перегрузка операторов new и delete
- •Преобразование типа
- •Явные преобразования типов
- •Преобразования типов, определенных в программе
- •Шаблоны Параметризированные классы
- •Передача в шаблон класса дополнительных параметров
- •Шаблоны функций
- •Совместное использование шаблонов и наследования
- •Шаблоны класса и friend
- •Некоторые примеры использования шаблона класса Реализация smart-указателя
- •Классы поддерживающие транзакции
- •Задание значений параметров класса по умолчанию
- •Пространства имен
- •Ключевое слово using как директива
- •Ключевое слово using как объявление
- •Псевдоним пространства имен
- •Организация ввода-вывода
- •Состояние потока
- •Строковые потоки
- •Организация работы с файлами
- •Организация файла последовательного доступа
- •Создание файла произвольного доступа
- •Основные функции классов ios, istream, ostream
- •Основы обработки исключительных ситуаций
- •Перенаправление исключительных ситуаций
- •Исключительная ситуация, генерируемая оператором new
- •Генерация исключений в конструкторах
- •Задание собственной функции завершения
- •Спецификации исключительных ситуаций
- •Задание собственного неожиданного обработчика
- •Иерархия исключений стандартной библиотеки
- •Стандартная библиотека шаблонов (stl) Общее понятие о контейнере
- •Общее понятие об итераторе
- •Категории итераторов
- •Основные итераторы
- •Вспомогательные итераторы
- •Операции с итераторами
- •Контейнерные классы Контейнеры последовательностей
- •Контейнер последовательностей vector
- •Контейнер последовательностей list
- •Контейнер последовательностей deque
- •Ассоциативные контейнеры
- •Ассоциативный контейнер multiset
- •Ассоциативный контейнер set
- •Ассоциативный контейнер multimap
- •Ассоциативный контейнер map
- •Адаптеры контейнеров
- •Адаптеры stack
- •Адаптеры queue
- •Адаптеры priority_queue
- •Пассивные и активные итераторы
- •Алгоритмы
- •Алгоритмы сортировки sort, partial_sort, sort_heap
- •Алгоритмы поиска find, find_if, find_end, binary_search
- •Алгоритмы fill, fill_n, generate и generate_n
- •Алгоритмы equal, mismatch и lexicographical_compare
- •Математические алгоритмы
- •Алгоритмы работы с множествами
- •Алгоритмы swap, iter_swap и swap_ranges
- •Алгоритмы copy, copy_backward, merge, unique и reverse
- •Примеры реализации контейнерных классов Связанные списки
- •Реализация односвязного списка
- •Реализация двусвязного списка
- •Реализация двоичного дерева
- •Литература
- •Вопросы по курсу ооп
- •220013, Минск, п.Бровки, 6.
Адаптеры queue
Класс queue предназначен для вставки элементов в конец базовой структуры данных и удаления элементов из ее начала. Адаптер queue реализуется с контейнерами list и deque (по умолчанию).
Наряду с общими для всех классов адаптеров операциями push, pop, empty и size в классе queue имеются операции front – получения ссылки на первый элемент очереди, back – ссылки на последний элемент очереди.
#include <iostream>
using std::cout;
using std::endl;
#include <queue>
// #include <list> для базового контейнера list
typedef int T;
main()
{ std::queue <T> och;
// std::queue <T, std::list<T> > lst; очередь на основе контейнера list
och.push(1); // занесение в очередь
och.push(2);
och.push(3);
int k=och.size(); // количество элементов в очереди
cout << "Очередь : ";
if(och.empty()) cout<<" пустая"; // проверка на пустоту очереди
else
{ for(int i=0;i<k;i++)
{ cout<<och.front()<<' '; // вывод значения первого элемента очереди
och.pop(); // удаление из очереди первого элемента
}
}
cout<<endl;
return 0;
}
Результат работы программы:
Очередь : 1 2 3
Инструкция
std::queue <T> och;
создает очередь для хранения в ней значений типа T. Очередь создается на основе контейнера deque по умолчанию. Функция front считывает значение первого элемента очереди, не удаляя его из нее. Для этого используется функция pop.
Адаптеры priority_queue
Класс priority_queue используется для вставки элементов в отсортированном порядке в базовую структуру данных и удаления элементов из ее начала. Адаптер priority_queue реализуется с контейнерами vector (по умолчанию) и deque.
Элементы в очередь с приоритетом заносятся в соответствии со своим значением. Это означает, что элемент с максимальным значением помещается в начало очереди и будет первым из нее удален, а с минимальным - в конец очереди. Это достигается с помощью метода, называемого сортировкой кучи. Сравнение элементов выполняется функцией-объектом less<Тип> или другой компораторной функцией.
Как и предыдущие адаптеры, priority_queue использует операции push, pop, empty, size, а также операцию top – получения ссылки на элемент с наивысшим приоритетом.
Пассивные и активные итераторы
Можно определять итерацию как часть объекта или создавать отдельные объекты, ответственные за итеративный опрос других структур. К достоинствам второго подхода относятся:
- наличие выделенного итератора классов, позволяющего одновременно проводить несколько просмотров одного и того же объекта;
- наличие итерационного механизма в самом классе несколько нарушает его инкапсуляцию, выделение итератора в качестве отдельного механизма поведения способствует достижению большей ясности в описании класса.
Для каждой структуры определены две формы итераций. Активный итератор требует каждый раз от клиента явного обращения к себе для перехода к следующему элементу. Пассивный итератор применяет функцию, предоставляемую клиентом, и, таким образом, требует меньшего вмешательства клиента. С целью обеспечения безопасности типов для каждой структуры создаются свои итераторы.
Ниже приведен пример использования активного итератора.
// --------------- реализация 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() { }
};
// ---------------- реализация 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; // итерация завершена
}
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
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() сама возвратит нулевое значение в знак того, что итерация не была завершена.