Представление иерархических отношений. Агрегация. Зависимость по времени жизни
Поможем в ✍️ написании учебной работы
Поможем с курсовой, контрольной, дипломной, рефератом, отчетом по практике, научно-исследовательской и любой другой работой

Агрегация возникает в тех случаях, когда один объект включает в себя в качестве составных частей другие объекты, например, когда один класс является коллекцией или контейнером других.

Причём по умолчанию, агрегацией называют агрегацию по ссылке, т.е. когда время существования содержащихся классов не зависит от времени существования содержащего их класса. Если контейнер будет уничтожен, то его содержимое нет.

Программная реализация агрегации (композиции) включает в себя:

· Включение в состав свойств описываемого класса одного или нескольких объектных свойств/указателей на соответствующие объекты

· Правильная реализация конструкторов составного класса

· Использование в составном классе свойств и методов включенных в него объектов

class citizen

{ ...... };

 

class country

{

std::vector<citizen*> population;

 

public:

void add_citizen(citizen* pc)

{

   population.push_back(pc);

}

voit remove_citizen(citizen* pc)

{

   population.erase(pc);

}

 

~country()

{

   // не удаляем граждан, пусть живут

}

};

Композиция более строгий вариант агрегации. Известна так же как агрегация по значению.

Композиция имеет жёсткую зависимость времени существования экземпляров класса контейнера и экземпляров содержащихся классов. Если контейнер будет уничтожен, то всё его содержимое будет также уничтожено.

class Engine

{

int power;

public Engine(int p)

{

   power = p;

  }

}

 

class Porshe

{

const std::string model = "Porshe";

   Engine engine;

public Car() : engine(360)

{}

}

(Двигатель не живет отдельно от Автомобиля)

 

7. Правила преобразования типов в C++. Параметрический и виртуальный полиморфизм.

Существует четыре категории преобразования типа:

static_cast() - тоже что и (T)

 

dynamic_cast() - используется для указателей и ссылок на полиморфные типы. Используется для динамического приведения типов во время выполнения. В случае неправильного приведения типов для ссылок вызывается исключительная ситуация std::bad_cast, а для указателей будет возвращен 0.

 

const _ cast - снятие CV — const и volatile (принимает указатели и ссылки)

 

                   int i;

const int * pi = &i;

// *pi имеет тип const int,

// но pi указывает на int, который константным не является

int* j = const_cast<int *> (pi);

 

reinterpret_cast - реинтерпретация участка памяти

Он изменяет тип данных в определенной области памяти, совершенно не задумываясь о том, имеет это смысл или нет.

     Например, удобно использовать для записи данных в бинарном виде

fout.write(reinterpret_cast<char*>(buff), MAX*sizeof(int));

 

· А также любой указатель может быть приведен к указателю на void* и наоборот.

 

Арифметические преобразования

В арифметических выражениях преобразования выполняются для того, чтобы привести значения к общему типу, который потом используется как тип результата. Если не учитывать беззнаковые типы, то можно удовлетвориться следующим набором неформальных правил:

 

1. Если какой-либо из операндов принадлежит типу double, то и другой приводится к double.

2. В противном случае, если какой-либо из операндов принадлежит типу float, то и другой приводится к float.

3. В противном случае операнды типов short, char, bool приводятся к int (в случае bool значение false переводится в 0, а true — в 1).

4. Наконец, если один из операндов типа long, то и другой приводится к long.

 

I. Параметрический полиморфизм (круто)

· Часто возникает необходимость в использовании функций одинаковых по семантике, но с разными типами или количеством аргументов (print, open, sqrt)

· Также часто возникает необходимость в использовании функций с аргументами совместимых типов

· Решение дают механизм перегрузки функций и правила разрешения параметрического полиморфизма

 

Разрешение перегрузки

1. Точное соответствие типов; в т.ч. соответствие, достигаемое тривиальным преобразованием типов (имя массива и указатель, имя функции и указатель на функцию, тип T и const T)

2. Соответствие, достигаемое «продвижением» интегральных типов (bool в int, char в int, short в int, в unsigned аналоги), float в double и double в long double

3. Соответствие, достигаемое путем стандартных преобразований ( int в double, double в int, указатели на производные типы в указатели на базовые, любые указатели в void*, T в unsigned T)

4. Соответствие, достигаемое путем преобразований, определяемых пользователем

class A {

public: A(int) {...}

};

 

class B {

public: operator A() {...}

……………..

  };

       Можно запретить неявное приведение типов если сделать конструктор explicit

  5. Соответствие за счет «...» в объявлении функции

int print(const char* format ...);

 

int main() {

A a;

B b;

int i = 10;

print(“ %A ”,a);

print(“ %B ”,b);

print(“ %d ”,i);

}

 

   Перегрузка и область видимости

Функции, объявленные в различных областях видимости (не пространствах имен) не являются перегруженными

 

Инстанцирование шаблонов

Тоже вид параметрического полиморфизма. Тут подробно рассказывать не буду. Главное, что надо сказать, шаблон определяет семейство классов (метакласс, ыыыы) или функций => результат инстанцирования с указанием параметров шаблона – функция или класс. Создаются только те классы и функции, которые потом используются в программе(что логично).

Дата: 2019-02-19, просмотров: 473.