Скачиваний:
151
Добавлен:
08.07.2017
Размер:
4.08 Mб
Скачать

Диаграммы взаимодействия (interaction diagrams) описывают взаимо действие групп объектов в различных условиях их поведения. UML определяет диаграммы взаимодействия нескольких типов, из которых наиболее употребительными являются диаграммы последовательности. Обычно диаграмма последовательности описывает один сценарий. На диаграмме показаны экземпляры объектов и сообщения, которыми обмениваются объекты в рамках одного прецедента (use case).

12. Архитектура и стиль программной реализации

Из ответов

Архитектура ­ это внутренняя структура программы. Стиль программной реализации – способ представления арх решений в программном коде. ​Связь – при плохом одном,

плохое и другое. 2 понятия стиля:

1)Примитивное. Цель – объяснить конкретный участок кода. Что входит: именование id­ров, комментарии, правила исп­ния goto, рефакторинги.

2)Современное. Цель – выразить арх решение. Включает: иерархия классов, реализации отношений, упр­ние видимостью, пространство имен и доступ, обработка исключит ситуаций, контроль аномал поведения пр­мы, проверка пред­ и постусловий, контроль инвариантов объектов, исп­ние шаблонов проектирования, исп­ние и фиксация вып­ных рефакторингов.

На арх­ру и стиль влияет исп­мый ЯП и библиотеки классов.

Идентификаторы и управление видимостью.

Объект на физическом уровне – идентиф­мая область памяти, которая м содержать значение объекта. Значение имеет связанное с ним имя и тип. Имя – либо идентификатор, либо выражение указывающее на объект.=> м сущ­ть безымянные объекты. Объявление делает известным идентификатор в данном контексте.

Определение ­ устанавливает связь идентификатора с типом и инициализирует объект, т.е. распределяет память, и возможно инициализирует значением. => Опр только одно (class P{..};), а объявлением м.б. много (class P;).

Явное управление видимостью, пространства имен.

Область действия id​– часть программы, где идентификатор может использоваться для доступа к объекту. Виды областей действия в С++:

1)Локальная или типа блок {__... };

2)оператор (до конца оператора – for(in i=…)),

3)прототип функции (до конца прототипа, ‘;’),

4)глобальная или файл (до конца файла),

5) класс

Пространство имен – область действия, где id д.б. уникален. В С++ действует общее пр­во имен для типов и нетипов. Поэтому действует след правило: не м.б. в одной обл­ти действия одно имя исп­но для 2х типов сразу. 2ое правило – если одно имя для одной обл­ти действия исп для типа и нетипа, то имя нетипа скрывает имя типа. (имя типа – класса, нетипа – переменная, ф­ция) Для доступа к имени типа следует исп­ть слово class: class Point a(1,1);

Область видимости – часть области действия, где id м.б. исп­н для нормального доступа к объектам. Обычно обл Д и В совпадают. Глобальный id м.б. скрыт локальным:

int a = 5; void f()

{

int a = 3;

int b = a; //a=3­­ использует локальную переменную

}

void h()

{

int c = a; //c=5­­ используется глобальная переменная

}

Продолжительность жизни объекта – время пока id­ру соответствует в памяти реал объект. Виды памяти:

1)статическая – память распред в начале вып­ния пр­мы и сохр до конца выполнения. Объекты: ­об с областью видимости типа файл (глобальная); ­с локал обл действия, но со специф обл­ти памяти static, extern (в другом файле находится этот объект); ­статич члены класса. Созд с пом конструктора, разруш с пом деструктора – вызыв. при завершении пр­мы автоматически. А если конструктор сделать как private или protected, то это явно запрещает создание таких объектов в пр­ме. Статич члены класса инициализ не в теле, а в глобал обл­ти действия., т.к. конструктор д.б. вызван лишь 1 раз

class Point

{

static int num = 0;

}

Point a, b; b.num = 5; a.num = 3;

std::cout << b.num; //b.num=3, так как num­­ static

2)локальная. Локал объекты. Хранятся в стеке. Созд конструктором, разруш деструктором при выходе из обл­ти дейтсвия. Если конструктор private/protected, то создать нельзя.

3) Динамическая. Временем созд и удалением упр­т программист с пом new и delete. Такие объекты располагаются в куче.

Point* a = new Point();

...

delete a;

Спецификаторы класса памяти

▪auto ​(действует по умолч для локал объектов)​, Point a;

auto b = a; //автоматически присваивает b тип, как у a, т.е. тип Point ▪extern (статич продолж жизни, внешний тип связывания),

▪ static (статич продолж жизни, внутр тип связыв), ▪register(рекомендация компилятору размещать объект в регистре)

Модификаторы​– хар­т изменчивость объекта: ▪const (предотв­т изменение объекта в памяти):

▪ volatile – асинхронно изм­мый или подвижный. Запрещает компилятору оптимизировать эту переменную. Указание компилятору на то, что знач объектов м.б. изм­ся асинхронно извне пр­мы.

int a=3; a=5;

int c = a;

Компилятор будет выполнять следующую последовательность: int a =5;

int c =a;

Но, если установить volatile, то выполнится все, что написано в программе volatile int a = 3;

▪ mutable – “мультируемый”. Член объекта м изм­ся даже если сам объект cost­ный

Управление обл­тью видимости В С++ id­ры м.б. явно сгруппированы в именованном пр­ве имен с пом конструкции namespace имя {}. Цель исп­ния – логич группировка имен в отлич от физич, к­рая реал­ся распределением id­ров по файлам и последующем вкл­м файла с исп­нием директивы include. С пом пр­ва имен м имитировать понятия пакета, интерфейса, и явно задавать зав­ти м/у классами.

Осн возможности:

▪Вне пр­ва имен имя, объявленное в нем, м.б. опр­но и исп­но с пом конструкции NS :: i к статич членам класса.

▪Допускается простр­ное X::Y::i (Y вложен в Х) namespace n1

{

namespace n2

{

static int a = 2;

}

}

int b = n1::n2::a; //b=2

▪М ввести в любую область вид­ти имя, описанное ранее: using x::i; после этого с i м работать без указания пр­ва имен. Аналогично м ввести все имена из пр­ва имен: using namespace X.

▪Конструкция using исп­ся также при наследовании для орг­ции правильного набора наслед­ных ф­ций в данном узле графа наследования.

▪В каждой единице трансляции сущ­т неимен­ное пр­во имен, доступ к кот осущ с пом

:: ▪Для пр­ва имен м вводить псевдонимы: namespaceTemplateLibrary namespace STL :: STL = StandartTemplateLibrary;

▪М объединять пр­ва имен: namespace Z {using namespace X; using namespaceY;}

▪М строить новые пр­во имен на основе отбора имен из других namespace Z{using X::f{};}

▪В имеющееся пр­во имен м добавлять новые имена namespace X {int g{};}

▪С исп­м пр­ва имен дополняются правила, действующие при перегрузке ф­ции. В случае вызова ф­ции без указания пр­ва имен, она ищется сперва в текущей обл­ти вид­ти, затем в пр­вах имен арг­тов, включая их классы и базовые классы, затем дейтс­т станд правила.

void h(int a); void h(int a, int b);

Пр­ва имен и проектирование интерфейса Цель использования пр­ва имен – локализовать код, т.ч. не было конфликта исп­ния имен.

13.Стиль реализации класса

Члены класса

Поле ​­ подобъект объекта (или класса в случае статического поля).

class Point

{

private:

int x; //поле int y; //поле

Point* next_point; //указатель

public:

Point() //конструктор по умолчанию

{ x = y = 0;} //т.е. х и у будут по умолчанию равф нулю void setXY(int x, int y); //метод

}

В зависимости от вида ассоциаций между классами поле может быть указателем, ссылкой или самим подобъектом.

1)Указатель: возникает вопрос о статусе владения объектом подобъекта. В библиотеках классов существуют средства для управления статусом владения. Например:

Косвенный контейнер может владеть хранимыми элементами, тогда при его уничтожении они должны уничтожаться.

Контейнер и внешний итератор: связь может быть разная. Например, ссылка на контейнер: итератор нельзя перенастроить в теч. жизни на другой контейнер.(Итератор­­ объект, который предоставляет доступ к элементам контейнера)

Метод: ​при проектирование набора методов определяется полный набор возможных методов для данного класса.

I.С точки зрения необходимости реализации рассматриваются следующие виды методов:

1)конструктор по умолчанию,

2)конструктор копирования,

3)конструктор с параметрами + конструктор преобразования типа из произвольного класса в данный A(const& B b) {getAFromB(b);}

4)деструктор

5)модификаторы (set)

6)селекторы (get)

7)операторы:

a)присваивания (=)

b)сравнения (==, !=)

c)больше, меньше (>, <)

8)операции преобразования типа (от данного класса в произвольный) (конструктор с нужным параметром, оператор преобразования типа) operator B() {}

9)итераторы для контейнеров (аппликаторы ­ функции)

II. Формируется интерфейс класса с совместным использованием (перегрузки) механизма присвоения начальных значений. Добавляются операции удобные пользователю и связанные с обработкой Exception.

Локальные и вложенные классы ­ традиционно так реализуются классы исключений, классы для проверки пред­, пост­ условий и инвариантов.

Инвариант представляет собой утверждение относительно класса. Например, класс Account (Счет) может иметь инвариант, который утверждает, что balance == sum(entries.amount()). Инвариант дол жен быть «всегда» истинным для всех экземпляров класса. В дан ном случае «всегда» означает «всякий раз, когда объект доступен для выполнения над ним операции».

Ссылки

type &rt = t; // rt ­ ссылка, t ­ инициализатор (обязателен кроме случаев внутри

класса или extern ссылок) void f(int& par1)

{

par1 = 2;

}

int a=3; f(a);

//а=2­­ так как объект передается по ссылке Ссылка ­ константный указатель на инициализатор или результат его

преобразования к типу type, при каждом использовании которого автоматически выполняется операция разыменования.

t инициализатор должен быть lvalue (переменной) (то, что слево от знака операции) и типа type иначе rt должна быть ссылкой на константу.

Семантика передачи параметров в методы определена как инициализация. void f (const int &rci){...} //при f(1.5) ­> const int &rci = 1.5;

Аналогично при возврате значения.

Если не const, то пусть f(x) (x double), тогда int &rci = x не может быть, т.к. double != int.

Если не const, то не беспокоимся ни о чем кроме несовместимости. Если нет const, то подразумевается изменение параметра внутри функции.

Ссылки применяются:

1.В качестве параметров методов для имитации способа передачи значений параметров по ссылке. Семантика передачи параметров и возврате значения в функцию определена как инициализация. Таким образом, отсутствие const в параметре ссылки явно запрещает использование преобразования типа “указывает на то, что передаваемый в функцию объект будет модифицирован ей”

2.Передача в методы больших структур данных (адрес структуры в памяти(без копирования)). Можно было бы использовать указатели, но это хуже, т.к. лишний уровень косвенности.

3.Использование ссылок в качестве возвращаемых значений функции.

Слева от оператора присваивания применяет конвеерную обработку:

f(obj) =f​(f​(f​(obj))); obj.setBla().setBoom().

1​2​3​

const Object& setBla() {...; return *this;} const Object& setBoom() {... return *this;}

Связь двух классов реализуется с помощью ссылки. Явно указывает на невозможность связи двух других экземпляров. Правильней всего в итераторе сделать поле ссылки на контейнер и инициализировать это поле в конструкторе итератора.

4. Использование ссылок для реализации функциональных объектов (функторов). void (*funcname) (int i, int j); void bla (int a, int b) funcname = bla;

Function

Манипулятор без параметров(функция как объект): typedef ostream & (*Omanip)(ostream &);

ostream & operator << (ostream &os, Omanip f) {return f(os);}

ostream & flush (ostream &); //сброс буфера в поток count << x << flush << y << flush;

Манипулятор с параметром: template <class T> class OManip

{

T i;

ostream & (*f)(ostream &,T); public:

OManip(osrteam &(*ff)(ostream &, T), T ii) : f(ff), i(ii) {};

friend ostream &operator << (ostream &os, Omanip &m) {return m.f(os, m.i); };

osrteam &precision (ostream &os, int i)

{

os.precision(i); return os; };

Omanip<int> setprecision(int i)

{

return Omanip<int>(&precision, i);

cout << setprecision(4) << x }​;

Пример:

#include <iostream.h> #include <iomanip.h> int main()

{

cout << setiosflags(ios::fixed);

cout << setprecision (2) << 1000.243 << endl; //endl­­ перевод каретки на новую строку­­ манипулятор без параметров

cout << setw (20) << "Hello there."; //setw­­ устанавливает ширину поля равной 20 ­­ манипулятор с параметром

return 0;

}

Локальные и вложенные классы.

Локальные (local) ­ класс, описанный внутри функции. void hello()

{

class SayHello

{

public:

void print()

{

std::cout << “Hello from SayHello”;

}

}

SayHello a; a.print();

}

int main()

{

hello();

}

Свойства:

1.Не должно быть статических членов.

2.Нет специального доступа.

3.Нельзя использовать автоматические переменные в классе.

4.Методы должны иметь только внутреннее описание. Применение:

1.Для сокращения глобального пространства имен.

2.Указания тесной семантической связи между функцией и классом (или классом

иклассом) ­ похоже на композицию.

Вложенный класс (nested) ­ описание внутри другого класса. class X {...class Y{};};

X::Y b; //использование Свойства:

1.В классе X нет подобъекта Y.

2.Нет специального доступа между членами X и Y.

3.Описание методов Y м.б. как внутренним, так и внешним.

Страуструп утверждает, что существует возможность выбора сделать класс другом или вложенным классом, на самом деле ­ дружба ­ это доступ, а вложенность ­ это видимость.

Доступ

Два способа использования: доступ к членам, доступ при наследовании.