
- •«Объектно-ориентированный анализ и проектирование»
- •1. Принципы ооп. Классы.
- •Описание классов.
- •Объекты класса.
- •Конструкторы
- •Конструктор копирования
- •Статические элементы класса
- •Дружественные функции и классы
- •Деструкторы
- •Перегрузка операций
- •Перегрузка унарных операций
- •Перегрузка бинарных операций
- •Перегрузка операции присваивания
- •Рекомендации по составу классов
- •2. Наследование
- •Ключи доступа
- •Простое наследование
- •Пример замещения функций (практикум)
- •Виртуальные методы
- •Множественное наследование
- •3. Отношения между классами. Диаграммы класссов на языке uml.
- •4. Шаблоны классов.
- •4.1. Определения шаблонов классов Queue и QueueItem
- •4.2. Конкретизация шаблона класса
- •4.3. Аргументы шаблона для параметров-констант
- •4.4. Функции-члены шаблонов классов
- •5. Обработка исключительных ситуаций
- •5.1. Общий механизм обработки исключений.
- •5.2 . Синтаксис исключений
- •5.3. Перехват исключений
- •5.4. Исключения в конструкторах и деструкторах
- •Vector(int n) // Конструктор
- •5.5. Список исключений функции.
- •6. Строки
- •Преобразование строк
- •7. Контейнерные классы
- •7.1. Векторы.
- •7.2. Двухсторонние очереди (deque).
- •7.3. Списки (List).
- •7.4. Стеки
- •7.5. Очереди (queue)
- •7.6. Очередь с приоритетами(priority_queue)
- •8. Ассоциативные контейнеры
- •8.1. Словари (map)
- •8.2. Словари с дубликатами (multimap)
- •8.3. Множества (set)
- •8.4. Множества с дубликатами (multiset)
- •8.5. Битовые множества (bitset)
7.4. Стеки
Стек – адаптер контейнера.
template <class T, class Container = deque<T>>
class stack{
protected:
Container c;
public:
explicit stack(const Container& = Container());
bool empty() {return c.empty();}
value_type& top(){return c.back();}
void push(const value_type& x){c.push_back(x);}
void pop(){c.pop_back();
…
}
Пример.
stack <int, vector<int>> st;
7.5. Очереди (queue)
Очередь - адаптер контейнера, который можно реализовать на основе списка или двухсторонней очереди (но не вектора), допускающая добавление в конец и удаление из начала.
template <class T, class Container = deque<T>>
class queue{
protected:
Container c;
public:
explicit queue(const Container& = Container());
bool empty() {return c.empty();}
value_type& front(){return c.front();}
value_type& back(){return c.back();}
void push(const value_type& x){c.push_back(x);}
void pop(){c.pop_front();}
…
}
7.6. Очередь с приоритетами(priority_queue)
Основано на контейнере с произвольным доступом, то есть двухсторонней очереди или векторе. Определен порядок выборки из очереди: «максимальный» элемент относительно операции «меньше».
template <class T, class Container = vector<T>,
class Compare = less<typename Container:: value_type>>
class priority_queue{
protected:
Container c;
Compare comp;
public:
explicit priority_queue(const Compare& = Compare()),
const Container& = Container());
…
bool empty() {return c.empty();}
const value_type& top() const{return c.back();}
void push(const value_type& x);
void pop();
…
}
#include <iostream>
#include <vector>
#include <functional>
#include <queue>
using namespace std;
void main()
{
priority_queue <int, vector<int>, greater<int> > P;
int x;
P.push(20);
P.push(10);
P.push(15);
P.push(34);
P.push(5);
while (!P.empty())
{
cout << P.top()<< endl;
P.pop();
}
}
Будет выдано:
5
10
15
20
34
В заголовочном файле functional существуют шаблоны сравнения: less<тип>, greater<тип>, less_equal<тип>, greater_equal<тип>. Для определения другого порядка выборки можно определить свой функциональный класс (то есть класс с элементом – вызовом функции).
8. Ассоциативные контейнеры
Как уже указывалось, ассоциативные контейнеры обеспечивают быстрый доступ к данным за счет того, что они, как правило, построены на основе сбалансированных деревьев поиска (стандартом регламентируется только интерфейс контейнеров, а не их реализация). Существует пять типов ассоциативных контейнеров: словари (mар), словари с дубликатами (multimap), множества (set), множества с дубликатами (multiset) и битовые множества (bitset). Словари часто называют также ассоциативными массивами или отображениями.
Словарь построен на основе пар значений, первое из которых представляет собой ключ для идентификации элемента, а второе — собственно элемент. Можно сказать, что ключ ассоциирован с элементом, откуда и произошло название этих контейнеров. Например, в англо-русском словаре ключом является английское слово, а элементом — русское. Обычный массив тоже можно рассматривать как словарь, ключом в котором служит номер элемента. В словарях, описанных в STL, в качестве ключа может использоваться значение произвольного типа. Ассоциативные контейнеры описаны в заголовочных файлах <mар> и <set>.
Для хранения пары «ключ—элемент» используется шаблон pair, описанный в заголовочном файле <utility>:
template<class T1, class T2> struct pair{
typedef T1 first_type;
typedef T2 second_type;
T1 first; T2 second;
pair();
pair(const T1 & x, const T2& y);
template <class U, class V> pair(const pair<U, V> &p);
};
Шаблон pair имеет два параметра, представляющих собой типы элементов пары. Первый элемент имеет имя first, второй — second. Определено два конструктора: один должен получать два значения для инициализации элементов, второй (конструктор копирования) - ссылку на другую пару. Конструктора по умолчанию у пары нет, то есть при создании объекта ему требуется присвоить значение явным образом.
Для пары определены проверка на равенство и операция сравнения на меньше (все остальные операции отношения генерируются в STL автоматически на основе этих двух операций). Пара p1 меньше пары р2, если p1.first < p2.first или р1.first == p2.first && p1.second < p2.second.
Для присваивания значения паре можно использовать функцию make_pair:
template<class T1, class T2> pair<T1, T2> make_pair(const T1& x, const T2& y);
Пример формирования пар:
#include <iostream>
#include <utility>
using namespace std;
int main(){
pair<int, double> p1(10, 12.3), p2(pl);
p3 = make_pair(20, 12.3); // Или р3 = pair <int, double>(20, 12.3)
cout << "p1: " << p2.first << ' ' << p2.second << '\n';
cout << "p3: " << p3.first << ' ' << p3.second << '\n';
p3.first -= 10;
if (p1 == p2) cout << "p1 == p3\n";
p1.second -= 1;
if (p3 > p1) cout << "p3 > p1\n";
}
Результат работы программы:
p1: 10 12.3
p2: 20 12.3
p1 == p3
p2 > p1
Заголовочный файл <utility> при использовании <map> или <set> подключается автоматически.