
- •«Объектно-ориентированный анализ и проектирование»
- •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)
Множественное наследование
Устранение неоднозначности
#include <fstream.h>
#include <iostream.h>
#include <stdlib.h>
class Base
{
protected:
int x;
public:
Base (int x1=0) { x = x1; }
};
class B: virtual public Base
{
public:
void AddB(int y) { x += y; }
};
class A: virtual public Base
{
public:
void AddA(int y) { x += 2*y; }
};
class D: public B, public A
{
public:
void Show() { cout << '='<< x<<endl; }
};
void main()
{
D d;
d.Show();
d.AddB(10);
d.Show();
d.AddA(10);
d.Show();
d.AddB(10);
d.Show();
}
Самостоятельная работа: разобрать задание из практикума «Функциональный калькулятор»
3. Отношения между классами. Диаграммы класссов на языке uml.
Язык UML – унифицированный язык моделирования является визуальным средством представления моделей программ. Модель программы – ее графическое представление в виде различных диаграмм, отражающих связи между объектами в программном коде. Диаграммы используют для описания шаблонов проектирования (design pattern), которые лежат в основе современного подхода к разработке программного обеспечения. Одной из основных диаграмм является диаграмма классов, описывающая классы и отражающая отношения между ними.
Класс изображается в виде прямоугольника, состоящего из 3-х частей, в которые записываются:
в верхнюю часть – имя класса;
в среднюю – список полей (атрибутов), возможно, с указанием типов и значений;
в нижнюю – список методов (операций), возможно, с указанием списка типов аргументов и типа возвращаемого значения.
Имя абстрактного класса и чисто виртуальных методов выделяются курсивом.
Перед именами могут стять символы ‘+’ – для public, ‘-’ – для private, ‘#’ – для protected, ‘&’ – для static.
Элементы несущественные на данном этапе абстракции могут быть опущены.
-
Monstr
-ammo: int
-health: int
-name: char *
-skin: color
+monstr(he=100:int, am=10:int)
+monstr(color)
+monstr(char*)
+monstr(monstr &)
+ void draw( )
Отношения между классами – это
Ассоциация – взаимодействие 2-х классов друг с другом. Над концами линии, соединяющей классы, может быть поставлено число (или *) для обозначения, сколько объектов (произвольное число) данного класса связано с одним объектов другого.
-
квартира
1
..* 1
дом
Ассоциация – наиболее абстрактная связь, которая в дальнейшем конкретизируется
Наследование – отношение обобщения («is a …»), которое обозначается линией со стрелкой в виде незакрашенного треугольника, направленной на базовый класс.
-
BaseClass
-
SunB1
SunB2
Агрегация обозначает, что один класс содержит в качестве составной части объекты другого класса («has a …»), то есть «целое - часть». Эта связь помечается стрелкой в виде ромба, указывающей на «целое». Ромб не закрашивается для нестрогой агрегации, когда «целое» может содержать не все объекты на схеме.
-
Гараж
-
легковой автомобиль
Автобус
Грузовик
В реализации на С++ удобно использовать в качестве полей указатели на компоненты («части»). Если компонент отсутствует, соответствующий указатель равен 0.
Для строгой агрегации, называемой композицией, при которой компонент не может исчезнуть пока «целое» существует, ромб закрашивается.
-
Triangle
3
Point
Композицию проще всего реализовывать включением объектов компонентов по значению. При включении по ссылке время существования компонентов должно перекрывать время жизни объекта-«целое».
Зависимость- отношения использования , когда один класс (клиент) пользуется услугами другого (сервер). Это происходит когда
метод клиента использует значения некоторых полей сервера;
метод клиента вызывает метод сервера;
метод клиента имеет сигнатуру, в которой упоминается сервер.
Эта связь помечается пунктирной стрелкой, указывающей на «сервер».
-
Triangle
Point
Проектирование программы с учетом будущих изменений.
Удачная декомпозиция характеризуется тем, что отдельные компоненты имеют сильное внутреннее сцепление и слабую внешнюю связанность (это упоминалось в начале представления курса).
Добавление новой функциональности довольно сложно выполнить в рамках структурного программирования. Одной из причин этого для процедурно-функциональных систем – использование конструкций на базе оператора выбора switch:
typedef enum {m1, m2, m3} ModeType
void func( ModeType m)
{
switch (m)
{
case m1: Func1(); break;
…
case m3: Func3();
}
}
В результате, перечень значений выборки заранее фиксирован и вся система разрабатывается с использованием ModeType. Добавление новой возможности для ModeType приводит к необходимости просмотра всего кода. Соответственно, требуется новое полное тестирование продукта.
В ООП грамотное использование полиморфизма и композиции классов позволяют решить проблему (причем использование «чистого» наследования не достаточно гибко). Самые удачные решения обобщаются в новом направлении, называемом шаблонами проектирования (design pattern). Пионерская работа принадлежит «банде четырех» (Э. Гамма (E.Gamma), Р. Хелм (R.Helm), Р Джонсон (R.Johnson), Дж. Влисседес (J.Vlissides)). В этой работе - GoF95 (Gang of Four, 1995) – были приведены 23 шаблона, предсталяющие собой диаграммы классов для решения часто встречающихся проблем с поясненими (имя, методы, примеры).
При создании проекта важен совет: «Найдите то, что может измениться в вашем дизайне и инкапсулируйте сущности, подверженные изменениям!» В нашем примере сущностями являются вызываемые функции. Следовательно, надо реализовывать функции как виртуальные методы полиморфных объектов. Соответствующая идея состоит в том, что объект класса «переключатель» имеет дело с абстракцией «функция вообще», реализованной через абстрактный класс (AbstrEn) с чисто виртуальным методом (Func). Конкретные функции – это одноименные методы в производных классах. «Переключатель» имеет информацию об адресах объектов этих (производных) классов, например, через список адресов (поле «Переключателя»), расположенных в векторе.
-
Переключатель
Адреса объектов:
En1,
En2,
…
p
AE: std::vector< AbstrEn *>
Select():AbstrEn*
К л и е н т
1..*
AbstrEn |
|
F unc() |
-
En1
En2
En3
Func()
Func()
Func()