2.49M
Категория: ПрограммированиеПрограммирование

Tagged union C++

1.

Лекция: Шаблоны проектирования (части 1-3)
1

2.

Содержание
1.1 Tagged union C++;
1.2 Варианты реализации списков;
1.3 Паттерн Итератор;
2.1 Паттерн Адаптер;
2.2 Умные указатели;
2.3 Идиома RAII;
2.4 RAII в процедурном стиле;
3.1 Функции обратного вызова;
3.2 Паттерн Делегирование;
3.3 Паттерны Посредник и Фасад;
3.4 Идиома PIMPL;
3.5 Выбор подходящего паттерна;
2

3.

1.1 Tagged union C++
3

4.

1.2 Варианты реализации списков
struct List {
string name;
double rate;
List* next, *prev;
};
4

5.

1.2 Варианты реализации списков
struct Node {
string name;
double rate;
Node* next, *prev;
};
struct List {
Node* first, *last;
}
5

6.

1.2 Варианты реализации списков
struct Student {
string name;
double rate;
}
struct Node {
Student student;
Node* next, *prev;
};
struct List {
Node* first, *last;
}
6

7.

1.2 Варианты реализации списков
1. Student* student;
2. template<T> … T* value;
2. выделенный узел для последнего узла;
3. size внутри List;
4. «Контракт» - оценка сложности операций, как реализовать
иначе? (односвязный + хэш-массив)
5. Итераторы?
7

8.

1.2 Варианты реализации списков
1. Student* student;
2. template<T> … T* value;
2. выделенный узел для последнего узла;
3. size внутри List;
4. «Контракт» - оценка сложности операций, как реализовать
иначе? (односвязный + хэш-массив)
5. Итераторы?
8

9.

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

10.

1.3 Итератор
10

11.

1.3 Итератор
Э. Гамма Приемы объектно-ориентированного проектирования. Паттерны проектир
Каковы последствия применения Итератора?
11

12.

2.1 Паттерн Адаптер (проблема)
12

13.

2.1 Паттерн Адаптер (классов и объектов)
13

14.

2.1 Паттерн Адаптер (пример)
14

15.

2.1 Паттерн Адаптер (пример)
15

16.

2.1 Паттерн Адаптер (пример)
16

17.

2.1 Паттерн Адаптер (пример)
17

18.

2.2 Умные указатели (проблема и решение)
18

19.

2.2 Умные указатели (пример)
19

20.

2.2 Умные указатели (пример)
20

21.

2.2 Умные указатели (пример)
21

22.

2.2 Умные указатели (виды)
shared_ptr
•Умный указатель, основанный на подсчете ссылок
•Обеспечивает совместное владение объектом
•Возможность управления не только памятью
•Накладные расходы
•Память для хранения счетчиков
•Thread-safe подсчет ссылок
weak_ptr (Слабая ссылка на объект):
Не влияет на время жизни
Автоматически обнуляется после удаления объекта
Пока объект жив, позволяет получить shared_ptr на него
Решает проблему циклических ссылок и висячих указателей
22

23.

2.2 Результаты применения умных указателей
1 Чистый код
2 Безопасность
3 Эффективность (по сравнению со сборщиками мусора)
4 Бывают разные (нужно выбрать)
Элджер Дж. C++. Библиотека программиста: Пер. с англ. — СПб.: Питер
23

24.

2.3 RAII
RAII классы обычно:
1) захватывают ресурс в конструкторе;
2) освобождают ресурс в деструкторе;
3) создаются на стеке (деструктор будет автоматически вызван
при раскручивании стека;
24

25.

2.3 RAII (пример)
25

26.

2.3 RAII (пример)
26

27.

2.3 RAII (рассуждение)
1) является ли Умный указатель RAII классом?
2) является ли Умный указатель Адаптером?
3) является ли Итератор RAII классом?
4) является ли Итератор Адаптером?
5) является ли Адаптер RAII-классом?
6) является ли RAII-класс Адаптером?
7) насколько трудно сделать хороший адаптер, RAII-класс? Что
для этого нужно сделать?
Джейсон Мак-Колм Смит Элементарные шаблоны проектирования : Пер. с
27

28.

2.4 RAII, Адаптер. Проблемы
Примеры:
●auto_ptr;
●fstream;
●многочисленные адаптеры/RAII-классы для OpenGL. Проблема в
данном случае:
●функция glBufferData вызывается для обновления сцены;
●функция glBufferSubData — для обновления части сцены.
28

29.

2.4 RAII в процедурном стиле
Разделяем Адаптер и RAII - теперь RAII-класс отвечает за создание и
уничтожение объекта, но не занимается построением интерфейса на все
случаи жизни. Аллокация ресурса в свободных функциях.
29

30.

3.1 Функции обратного вызова
Примеры использования:
●qsort /std::sort;
●механизм оповещения
●о событиях;
●QTimer?
●еще?
Что дает? Что такое Функционалы и зачем они применяются?
30

31.

3.1 Функции обратного вызова
Особенности реализации:
●Как обернуть выполняемый код?
●Как передать код в качестве аргумента?
●Как передать контекст?
31

32.

3.1 Функции обратного вызова.
Указатель на функцию / статический метод класса
Достоинства:
●просто;
●гибко (слабые связи).
Недостатки:
●сервер не может сохранить контекст;
●неудобно передавать контекст.
32

33.

3.1 Функции обратного вызова.
Указатель на метод класса
Достоинства:
контекст внутри класса;
Недостатки:
●связи сильнее;
●сервер должен хранить оба указателя.
Будет ли работать с виртуальными функциями?
33

34.

3.1 Функции обратного вызова.
Указатель на метод класса. Реализация
34

35.

3.1 Функции обратного вызова.
Указатель на функциональный объект
Достоинства:
●не нужно явно передавать контекст;
Недостатки:
●не всегда подойдет (qsort, системные функции, ...)
35

36.

3.1 Функции обратного вызова.
Указатель на функциональный объект. Реализация
36

37.

Достоинства:
●элегантная реализация;
●максимально гибко.
3.1 Функции обратного вызова.
Лямбда-функции и std::functional
37

38.

3.2 Паттерн Делегирование
Делегирование — базовый шаблон проектирования, в котором объект
внешне выражает некоторое поведение, но в реальности передаёт
ответственность за выполнение этого поведения связанному объекту.
Как это связано с функциями обратного вызова?
Альтернатива наследованию?
Итератор — это делегирование?
Адаптер — это делегирование?
RAII — это делегирование?
Умный указатель — это делегирование?
Как это связано с Чистой архитектурой?
38

39.

Мини-задание:
1. Изобразить отношения между шаблонами проектирования и идиомами:
Итератор, Адаптер, RAII, Делегирование с помощью нотации диаграммы
классов UML.
2.
39

40.

3.3 Паттерны Посредник и Фасад
Взаимодействие множества объектов;
●Обеспечение слабой связности.
●Инкапсуляция способа взаимодействия;
Сокрытие сложности за простым и
стабильным интерфейсом;
●Фасад — это Адаптер?
●Фасад — это Делегирование?
●Фасад — это Посредник?
●Посредник — это Фасад?
40

41.

3.4 Идиома PIMPL. Пример. Часть 1
Фрагмент файла raw_socket.h:
На этом и двух следующих слайдах — пытаемся понять, «чего
хотел добиться автор исходного кода?»
41

42.

3.4 Идиома PIMPL. Пример. Часть 2
Фрагмент файла raw_socket.cpp:
42

43.

3.4 Идиома PIMPL. Пример. Часть 3
Фрагмент файла raw_socket.inl:
43

44.

3.4 Идиома PIMPL
Предположим, что вам необходимо воспользоваться внешним API,
но при этом вы не хотите:
1) позволить платформно-зависимому коду расползаться по
проекту;
2) чтобы у пользователя была возможность им воспользоваться
напрямую.
Итог: Пользователь класса
network::raw_socket не сможет
напрямую работать с сокетом,
так как включение системных
заголовочных файлов происходит
внутри cpp-файла.
44

45.

3.5 Выбор подходящего паттерна
Какая польза от применения паттернов и идиом? (перечислить)
Адаптер — это хорошо или плохо? (порассуждать)
Что не является адаптером?
PIMPL — это адаптер?
PIMPL — это фасад?
PIMPL — это RAII?
PIMPL — это делегирование?
Зачем в ООП Интерфейсы? (привести примеры)
Влиссидес Джон. Применение шаблонов проектирования. Дополнительные шт
45

46.

3.5 Выбор подходящего паттерна
46
English     Русский Правила