- •Содержание
- •ВВЕДЕНИЕ
- •1.ОБЪЕКТНО-ОРИЕНТИРОВАННЫЙ ПОДХОД
- •2. ОБЪЕКТНО-ОРИЕНТИРОВАННОЕ ПРОГРАММИРОВАНИЕ
- •2.1. Абстрактные типы данных
- •2.2. Базовые принципы объектно-ориентированного программирования
- •2.3. Основные достоинства языка С++
- •2.4. Особенности языка С++
- •2.4.1. Ключевые слова
- •2.4.2. Константы и переменные
- •2.4.3. Операции
- •2.4.4. Типы данных
- •2.4.5. Передача аргументов функции по умолчанию
- •2.5.1. Объект cin
- •2.5.2. Объект cout
- •2.5.3. Манипуляторы
- •3.1. Объекты
- •3.2. Понятие класса
- •3.3. Конструктор копирования
- •3.4. Конструктор explicit
- •3.5. Указатель this
- •3.6. Встроенные функции (спецификатор inline)
- •3.7. Организация внешнего доступа к локальным компонентам класса (спецификатор friend)
- •3.8. Вложенные классы
- •3.9. Static-члены (данные) класса
- •3.10. Компоненты-функции static и const
- •3.11. Proxi-классы
- •3.12. Ссылки
- •3.12.1. Параметры ссылки
- •3.12.2. Независимые ссылки
- •3.13. Пространства имен
- •3.13.3. Ключевое слово using как объявление
- •3.13.4. Псевдоним пространства имен
- •3.14. Практические приемы ограничения числа объектов класса
- •4. НАСЛЕДОВАНИЕ
- •4.1.1. Конструкторы и деструкторы при наследовании
- •4.2. Виртуальные функции
- •4.3. Абстрактные классы
- •4.4. Виртуальные деструкторы
- •4.6. Виртуальное наследование
- •5.2. Перегрузка операторов
- •5.2.2. Перегрузка унарного оператора
- •5.2.3. Дружественная функция operator
- •5.2.4. Особенности перегрузки операции =
- •5.2.5. Перегрузка оператора []
- •5.2.6. Перегрузка оператора ()
- •5.2.7. Перегрузка оператора ->
- •5.2.8. Перегрузка операторов new и delete
- •5.3. Преобразование типа
- •5.3.1. Явные преобразования типов
- •6. ШАБЛОНЫ
- •6.1. Параметризированные классы
- •6.2. Передача в шаблон класса дополнительных параметров
- •6.3. Шаблоны функций
- •6.4. Совместное использование шаблонов и наследования
- •6.5. Шаблоны класса и friend-функции
- •6.6. Некоторые примеры использования шаблона класса
- •6.6.1. Реализация smart-указателя
- •6.6.2. Задание значений параметров класса по умолчанию
- •7.2. Состояние потока
- •7.3. Строковые потоки
- •7.4. Организация работы с файлами
- •7.5. Организация файла последовательного доступа
- •7.6. Создание файла произвольного доступа
- •7.7. Основные функции классов ios, istream, ostream
- •8. ИСКЛЮЧЕНИЯ В С++
- •8.2. Перенаправление исключительных ситуаций
- •8.3. Исключительная ситуация, генерируемая оператором new
- •8.6. Спецификации исключительных ситуаций
- •8.7. Задание собственного неожиданного обработчика
- •9. СТАНДАРТНАЯ БИБЛИОТЕКА ШАБЛОНОВ (STL)
- •9.3. Категории итераторов
- •9.4. Операции с итераторами
- •9.5. Контейнеры последовательностей
- •9.5.2. Контейнер последовательностей list
- •9.5.3. Контейнер последовательностей deque
- •9.6. Ассоциативные контейнеры
- •9.6.1. Ассоциативный контейнер multiset
- •9.6.2. Ассоциативный контейнер set
- •9.6.3. Ассоциативный контейнер multimap
- •9.7.1. Адаптер stack
- •9.7.2. Адаптер queue
- •9.7.3. Адаптер priority_queue
- •9.8. Алгоритмы
- •9.8.1. Алгоритмы сортировки sort, partial_sort, sort_heap
- •9.8.2. Алгоритмы поиска find, find_if, find_end, binary_search
- •9.8.3. Алгоритмы fill, fill_n, generate и generate_n
- •9.8.4. Алгоритмы equal, mismatch и lexicographical_compare
- •9.8.6. Алгоритмы работы с множествами
- •9.8.7. Алгоритмы swap, iter_swap и swap_ranges
- •9.8.8. Алгоритмы copy, copy_backward, merge, unique и reverse
- •10. ПРИМЕРЫ РЕАЛИЗАЦИИ КОНТЕЙНЕРНЫХ КЛАССОВ
- •10.1. Связанные списки
- •10.1.1. Реализация односвязного списка
- •10.2. Реализация бинарного дерева
- •11. ПРОГРАММИРОВАНИЕ ДЛЯ WINDOWS
- •11.1. Система, управляемая сообщениями
- •11.2. Управление графическим выводом
- •11.3. Контекст устройства
- •11.3.1. Экран
- •11.3.2. Принтер
- •11.3.3. Объект в памяти
- •11.3.4. Информационный контекст
- •11.4. Архитектура, управляемая событиями
- •11.5. Исходный текст программы
- •11.7. Некоторые новые типы данных
- •11.8. Венгерская нотация
- •11.9. Точка входа программы
- •11.11. Создание окна
- •11.12. Цикл обработки сообщений
- •11.13. Оконная процедура
- •11.14. Обработка сообщений
- •11.15. Обработка сообщений функцией DefWindowProc
- •11.16. Синхронные и асинхронные сообщения
- •11.17. Еще один метод получения описателя контекста устройства
- •11.19. Полосы прокрутки
- •Литература
щие во второе;
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