SlideShare ist ein Scribd-Unternehmen logo
1 von 53
Downloaden Sie, um offline zu lesen
Углубленное
программирование
на языке C++
Алексей Петров
Лекция №4. Специальные
вопросы наследования
и полиморфизма
1. Инициализация, копирование,
преобразование и уничтожение объектов
(продолжение). Идиома RAII.
2. Раннее и позднее связывание. Перегрузка
и перекрытие членов класса.
3. Виртуальные функции. Абстрактные
классы. Множественное и виртуальное
наследование.
4. RTTI и операции приведения типов.
Производительность и безопасность
полиморфизма и средств поддержки RTTI.
5. Постановка задач к практикуму №4.

2
Инициализация без конструктора (1 / 2)
Класс, все члены которого открыты, может задействовать
механизм явной позиционной инициализации, ассоциирующий
значения в списке инициализации с членами данных в
соответствии с их порядком.
class Test
{
public:
int
int_prm;
double dbl_prm;
string str_prm;
};
// …
Test test = { 1, -3.14, "dictum factum" };
3
Инициализация без конструктора (2 / 2)
Преимуществами такой техники выступают:
 скорость и эффективность, особо значимые при выполнении во
время запуска программы (для глобальных объектов).

Недостатками инициализации без конструктора являются:
 пригодность только для классов, члены которых открыты;
 отсутствие поддержки инкапсуляции и абстрактных типов;
 требование предельной точности и аккуратности в применении.

4
Конструкторы по умолчанию (1 / 2)
Конструктор по умолчанию не требует задания значений его
параметров, хотя таковые могут присутствовать в сигнатуре.
class Test
{
public:
Test(int ipr = 0, double dpr = 0.0);
/* … */
};

Наличие формальных параметров в конструкторе по умолчанию
позволяет сократить общее число конструкторов и объем
исходного кода.
5
Конструкторы по умолчанию (2 / 2)
Если в классе определен хотя бы один конструктор с параметрами,
то при использовании класса со стандартными контейнерами и
динамическими массивами экземпляров конструктор по
умолчанию обязателен.
Test *tests = new Test[TEST_PLAN_SIZE];

Если конструктор по умолчанию не определен, но существует
хотя бы один конструктор с параметрами, в определении объектов
должны присутствовать аргументы. Если ни одного конструктора
не определено, объект класса не инициализируется (память под
статическими объектами по общим правилам обнуляется).
6
Конструкторы с параметрами: пример

class Test
{
public:
Test(int prm) : _prm (prm) {}
private:
int
_prm;
};
// все вызовы конструктора допустимы и эквивалентны
Test
test1(10),
test2 = Test(10),
test3 = 10;
// для одного аргумента

7
Массивы объектов: пример

// массивы объектов класса определяются
// аналогично массивам объектов базовых типов
// для конструктора с одним аргументом
Test testplan1[] = { 10, -5, 0, 127 };
// для конструктора с несколькими аргументами
Test testplan2[5] = {
Test(10, 0.1),
Test(-5, -3.6),
Test(0, 0.0),
Test() // если есть конструктор по умолчанию
};

8
Закрытые и защищенные конструкторы
Описание конструктора класса как защищенного или закрытого
дает возможность ограничить или полностью запретить отдельные
способы создания объектов класса.
В большинстве случаев закрытые и защищенные конструкторы
используются для:
 предотвращения копирования одного объекта в другой;

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

9
Почленная инициализация
и присваивание (1 / 2)
Почленная инициализация по умолчанию — механизм
инициализации одного объекта класса другим объектом того же
класса, который активизируется независимо от наличия в
определении класса явного конструктора.
Почленная инициализация по умолчанию происходит в следующих
ситуациях:
 явная инициализация одного объекта другим;
 передача объекта класса в качестве аргумента функции;
 передача объекта класса в качестве возвращаемого функцией значения;

 определение непустого стандартного последовательного контейнера;
 вставка объекта класса в стандартный контейнер.
10
Почленная инициализация
и присваивание (2 / 2)
Почленная инициализация по умолчанию подавляется при
наличии в определении класса конструктора копирования.
Запрет почленной инициализации по умолчанию осуществляется
одним из следующих способов:
 описание закрытого конструктора копирования (не действует для
методов класса и дружественных объектов);
 описание конструктора копирования без его определения (действует
всюду).

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

11
Конструкторы копирования
Конструктор копирования принимает в качестве единственного
параметра константную ссылку на существующий объект класса.
В случае отсутствия явного конструктора копирования в
определении класса производится почленная инициализация
объекта по умолчанию.
class Test
{
/* … */
Test(const Test &other);
/* … */
};
12
Конструкторы
и операции преобразования
Конструкторы преобразования служат для построения объектов
класса по одному или нескольким значениям иных типов.
Операции преобразования позволяют преобразовывать
содержимое объектов класса к требуемым типам данных.
class Test
{
// конструкторы преобразования
Test(const char *);
Test(const string &);
// операции преобразования
operator int
() { return int_prm; }
operator double () { return dbl_prm; }
/* … */
};
13
Деструкторы.
Виртуальные деструкторы (1 / 2)
Деструктор — не принимающий параметров и не возвращающий
результат метод класса, автоматически вызываемый при выходе
объекта из области видимости и применении к указателю на
объект класса операции delete.
class Test
{
/* … */
virtual ~Test();
};

Примечание: деструктор не вызывается при выходе из области
видимости ссылки или указателя на объект.
14
Деструкторы.
Виртуальные деструкторы (2 / 2)
Типичные задачи деструктора:
 сброс содержимого программных буферов в долговременные хранилища;
 освобождение (возврат) системных ресурсов, главным образом —
оперативной памяти;
 закрытие файлов или устройств;
 снятие блокировок, останов таймеров и т.д.

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

15
Идиома RAII
Закрепление за конструкторами функции захвата, выделения,
блокировки или инициализации ресурсов, а за деструкторами —
функции их возврата, освобождения и снятия установленных
блокировок:
 позволяет безопасно обрабатывать ошибки и исключения;
 составляет суть одной из важнейших идиом ОО-программирования RAII
(англ. Resource Acquisition Is Initialization — «получение ресурса есть
инициализация»).

Работа идиомы RAII в языке C++ основана, главным образом, на
гарантированном вызове деструкторов автоматических
переменных, являющихся экземплярами классов, при выходе из
соответствующих областей видимости.
16
Явный вызов деструкторов
Потребность в явном вызове деструктора обычно связана с
необходимостью уничтожить динамически размещенный объект
без освобождения памяти.
char *buf = new char[sizeof(Test)];
// "размещающий" вариант new
Test *ptc = new (buf) Test(100);

/* … */
ptc->~Test();
// вызов 1
Test *ptc = new (buf) Test(200);
/* … */
ptc->~Test(); // вызов 2
delete [] buf;
17
Список инициализации в конструкторе
Выполнение любого конструктора состоит из двух фаз:
 фаза явной (неявной) инициализации (обработка списка
инициализации) — предполагает начальную инициализацию членов
данных;
 фаза вычислений (исполнение тела конструктора) — предполагает
присваивание значений (в предварительно инициализированных
областях памяти).

Присваивание значений членам данных – объектам классов в
теле конструктора неэффективно ввиду ранее произведенной
инициализации по умолчанию. Присваивание значений членам
данных, представляющих базовые типы, по эффективности
равнозначно инициализации.
К началу исполнения тела конструктора все константные
члены и члены-ссылки должны быть инициализированы.

18
Семантика переноса (C++11)
Введение в С++11 семантики переноса (англ. move semantics)
обогащает язык возможностями более тонкого и
эффективного управления памятью данных, устраняющего
копирование объектов там, где оно нецелесообразно.
Технически семантика переноса реализуется при помощи
ссылок на праводопустимые выражения и конструкторов
переноса.
Конструкторы переноса не создают точную копию своего
параметра, а перенастраивают параметр так, чтобы права
владения соответствующей областью памяти были переданы
вновь создаваемому объекту («заимствованы» последним).
Аналогично работают операции присваивания с переносом.
19
Конструктор переноса: пример (1 / 2)

class Alpha {
public:
Alpha();
Alpha(const Alpha &a); // конструктор копирования
Alpha(Alpha &&a);
// конструктор переноса
~Alpha();
private:
size_t sz;
double *d;
};
Alpha::Alpha() : sz(0), d(0) { }
Alpha::~Alpha() {
delete [] d;
}

20
Конструктор переноса: пример (2 / 2)

// конструктор копирования
Alpha::Alpha(const Alpha &a) : sz(a.sz)
{
d = new double[sz];
/* … */
for(size_t i = 0; i < sz; i++)
d[i] = a.d[i];
}

// конструктор переноса
Alpha::Alpha(Alpha &&a) : sz(a.sz)
{
d
= a.d;
// перенастройка параметра
a.d = nullptr; // C++11
a.sz = 0;
}
21
Наследование: ключевые понятия
Наследование содействует повторному использованию атрибутов
и методов класса, а значит, делает процесс разработки ПО более
эффективным. Возникающие между классами A и B отношения
наследования позволяют, например, говорить, что:
 класс A является базовым (родительским) классом, классом-предком,
надклассом (англ. superclass);
 класс B является производным (дочерним) классом, классом-потомком,
подклассом (англ. subclass).

Отношения наследования связывают классы в иерархию
наследования, вид которой зависит от числа базовых классов у
каждого производного:
 при одиночном наследовании иерархия имеет вид дерева;
 при множественном наследовании — вид направленного
ациклического графа (НАГ) произвольного вида.

22
Наследование: примеры (UML)

Одиночное наследование (слева), множественное наследование (в центре,
классы Alpha и Alpha (II) идентичны), виртуальное множественное
наследование (справа)
23
Полиморфизм подклассов
В том случае если базовый и производный классы имеют общий
открытый интерфейс, говорят, что производный класс
представляет собой подкласс базового.
Отношение между классом и подклассом, позволяющее указателю
или ссылке на базовый класс без вмешательства программиста
адресовать объект производного класса, возникает в C++
благодаря поддержке полиморфизма.
Полиморфизм позволяет предложить такую реализацию ядра
объектно-ориентированного приложения, которая не будет
зависеть от конкретных используемых подклассов.

24
Раннее и позднее связывание
В рамках классического объектного подхода, — а равно и
процедурного программирования, — адрес вызываемой функции
(метода класса) определяется на этапе компиляции (сборки). Такой
порядок связывания вызова функции и ее адреса получил
название раннего (статического).
Позднее (динамическое) связывание состоит в нахождении
(разрешении) нужной функции во время исполнения кода. При
этом работа по разрешению типов перекладывается с
программиста на компилятор.
В языке C++ динамическое связывание поддерживается
механизмом виртуальных методов класса, для работы с которыми
компиляторы строят таблицы виртуальных методов (англ. VMT,
virtual method table).
25
Базовые и производные классы
ОО-проектирование допускает существование классов, которые
могут выполнять чисто технические функции, моделировать
абстрактные сущности и отличаться функциональной неполнотой:
• не подлежащий реализации в виде экземпляров (объектов) базовый
класс может оставаться абстрактным. В противовес абстрактным
базовым классам классы, предполагающие создание экземпляров,
именуют конкретными;

• (абстрактные) базовые классы специфицируют открытые интерфейсы
иерархий и содержат общие для всех подклассов атрибуты и методы
(или их прототипы).

Множество подклассов любого базового класса ограничено
иерархией наследования, но потенциально бесконечно (ввиду
отсутствия пределов по расширению иерархии вглубь и вширь).
26
Определение наследования
Определение отношения наследования имеет вид (для
одиночного наследования):
// заголовок класса
class <имя производного класса> :
<уровень доступа> <имя базового класса>
// тело класса
{
/* … */
};

где <уровень доступа> — ключевое слово public, private или
protected, а <имя базового класса> — имя ранее определенного
(не описанного!) класса.
В зависимости от уровня доступа к членам базового класса
говорят об открытом, закрытом или защищенном наследовании.
27
Определение наследования: пример

// описание производного класса
// (не включает список базовых классов!)
class Deposit;
/* … */
// определения классов
class Account
{
/* … */
};
class Deposit : public Account
{
/* … */
};
28
Защищенные и закрытые члены класса
Атрибуты и методы базового класса, как правило, должны быть
непосредственно доступны для производных классов и
непосредственно недоступны для прочих компонентов программы.
В этом случае они помещаются в секцию protected, в результате
чего защищенные члены данных и методы базового класса:
 доступны производному классу (прямому потомку);
 недоступны классам вне рассматриваемой иерархии, глобальным
функциям и вызывающей программе.

Если наличие прямого доступа к члену класса со стороны
производных классов нежелательно, он вводится как закрытый.
Закрытые члены класса не наследуются потомками. Для доступа к
ним класс-потомок должен быть объявлен в классе-предке как
дружественный. Отношения дружественности не наследуются.
29
Перегрузка и перекрытие
членов класса
Члены данных базового класса могут перекрываться
одноименными членами данных производного класса, при этом
их типы не должны обязательно совпадать. (Для доступа к
члену базового класса его имя должно быть
квалифицировано.)
Методы базового и производного классов не образуют
множество перегруженных функций. В этом случае методы
производного класса не перегружают (англ. overload), а
перекрывают (англ. override) методы базового.
Для явного создания объединенного множества
перегруженных функций базового и производного классов
используется объявление using, которое вводит именованный
член базового класса в область видимости производного.

30
Перегрузка и перекрытие
членов класса: пример
Примечание: в область видимости производного класса попадают
все одноименные методы базового класса, а не только некоторые
из них.
class Account
{ /* … */
void display(const char *fmt);
void display(const int mode = 0);
};
class Deposit : public Account
{
void display(const string &fmt);
using Account::display;
/* … */
};

31
Порядок вызова конструкторов
производных классов (1 / 2)
Порядок вызова конструкторов объектов-членов, а также
базовых классов при построении объекта производного класса
не зависит от порядка их перечисления в списке инициализации
конструктора производного класса и является следующим:
 конструктор базового класса (если таковых несколько, конструкторы
вызываются в порядке перечисления имен классов в списке базовых
классов);
 конструктор объекта-члена (если таковых несколько, конструкторы
вызываются в порядке объявления членов данных в определении
класса);
 конструктор производного класса.

32
Порядок вызова конструкторов
производных классов (2 / 2)
Конструктор производного класса может вызывать конструкторы
классов, непосредственно являющихся базовыми для данного
(прямых предков), и — без учета виртуального наследования —
только их.
Примечание: правильно спроектированный конструктор
производного класса не должен инициализировать атрибуты
базового класса напрямую (путем присваивания значений).

33
Список инициализации при
наследовании: пример
class Alpha {
public:
// Alpha();
Alpha(int i); /* … */
};
class Beta : public Alpha {
public:
Beta() : _s("dictum factum") { }
// Beta() : Alpha(), _s("dictum factum") { }
Beta(int i, string s) : Alpha(i), _s(s) { }
protected:
string _s; /* … */
};

34
Порядок вызова деструкторов
производных классов
Порядок вызова деструкторов при уничтожении объекта
производного класса прямо противоположен порядку вызова
конструкторов и является следующим:
 деструктор производного класса;
 деструктор объекта-члена (или нескольких);
 деструктор базового класса (или нескольких).

Взаимная противоположность порядка вызова конструкторов и
деструкторов является строгой гарантией языка C++.

35
Виртуальные функции (1 / 2)
Методы, результат разрешения вызова которых зависит от
«реального» (динамического) типа объекта, доступного по
указателю или ссылке, называются виртуальными и при
определении в базовом классе снабжаются спецификатором
virtual.
Примечание: в этом контексте тип непосредственно определяемого
экземпляра, ссылки или указателя на объект называется
статическим. Для самого объекта любого типа (автоматической
переменной) статический и динамический тип совпадают.
По умолчанию объектная модель C++ работает с невиртуальными
методами. Механизм виртуальных функций работает только в
случае косвенной адресации (по указателю или ссылке).
36
Виртуальные функции (2 / 2)
Значения формальных параметров виртуальных функций
определяются (а) на этапе компиляции (б) типом объекта,
через который осуществляется вызов.
Отмена действия механизма виртуализации возможна и
достигается статическим вызовом метода при помощи
операции разрешения области видимости (::).
class Alpha {
/* … */
virtual void display();
};
class Beta : public Alpha {
void display();
}
37
Чистые виртуальные функции
Класс, где виртуальный метод объявляется впервые, должен
определять его тело либо декларировать метод как не имеющую
собственной реализации чистую виртуальную функцию.
Производный класс может наследовать реализацию
виртуального метода из базового класса или перекрывать его
собственной реализацией, при этом прототипы обеих реализаций
обязаны совпадать.
virtual void display() = 0;

Примечание: единственное исключение С++ делает для
возвращаемого значения. Значение, возвращаемое реализацией
в производном классе, может иметь тип, открыто наследующий
классу значения, возвращаемого реализацией в базовом.
38
Абстрактные классы
Класс, который определяет или наследует хотя бы одну чистую
виртуальную функцию, является абстрактным.
Экземпляры абстрактных классов создавать нельзя. Абстрактный
класс может реализовываться только как подобъект
производного, неабстрактного класса.
Чистые виртуальные функции могут иметь тело, вызов которого,
впрочем, может производиться только статически (при помощи
операции разрешения области видимости), но не динамически (при
помощи механизма виртуализации).

39
Чистые виртуальные функции
и абстрактные классы: пример
// class Alpha;
// class Beta : public Alpha;
virtual void Alpha::display() { /* … */ };
void Beta::display()
{
// вызов чистой виртуальной функции
Alpha::display();
/* … */
}

40
Множественное наследование
Множественное наследование в ООП — это наследование от
двух и более базовых классов, возможно, с различным уровнем
доступа. Язык C++ не накладывает ограничений на количество
базовых классов.
При множественном наследовании конструкторы базовых классов
вызываются в порядке перечисления имен классов в списке
базовых классов. Порядок вызова деструкторов ему прямо
противоположен.
Унаследованные от разных базовых классов методы не образуют
множество перегруженных функций, а потому разрешаются
только по имени, без учета их сигнатур.
41
Виртуальное наследование
При множественном наследовании возможна ситуация
неоднократного включения подобъекта одного и того же базового
класса в состав производного. Связанные с нею проблемы и
неоднозначности снимает виртуальное наследование.
Суть виртуального наследования — включение в состав класса
единственного разделяемого подобъекта базового класса
(виртуального базового класса).
Виртуальное наследование не характеризует базовый класс, а
лишь описывает его отношение к производному.

Использование виртуального наследования должно быть
взвешенным проектным решением конкретных проблем объектноориентированного проектирования.
42
Конструкция объектов при виртуальном
наследовании
Виртуальные базовые классы конструируются перед
невиртуальными независимо от их расположения в иерархии
наследования.
Ответственность за инициализацию виртуального базового класса
несет на себе ближайший (финальный) производный класс.
В промежуточных производных классах прямые вызовы
конструкторов виртуальных базовых классов автоматически
подавляются.

43
Множественное и виртуальное
наследование: пример
// множественное наследование
class Alpha
{ /* … */ };
class Beta : public Alpha
{ /* … */ };
class Gamma
{ /* … */ };
class Delta : public Beta, public Gamma
{ /* … */ };
// виртуальное наследование
class Alpha
{ /* … */ };
class Beta : virtual public Alpha
// то же: class Beta : public virtual Alpha
{ /* … */ };

44
Динамическая идентификация
типов времени выполнения (RTTI)
Динамическая идентификация типов времени выполнения (англ.
Real-Time Type Identification) обеспечивает специальную
поддержку полиморфизма и позволяет программе узнать
реальный производный тип объекта, адресуемого по ссылке или
по указателю на базовый класс. Поддержка RTTI в C++
реализована двумя операциями:
 операция dynamic_cast поддерживает преобразование типов времени
выполнения;
 операция typeid идентифицирует реальный тип выражения.

Операции RTTI — это события времени выполнения для классов с
виртуальными функциями и события времени компиляции для
остальных типов. Исследование RTTI-информации полезно, в
частности, при решении задач системного программирования.
45
Операция dynamic_cast
Встроенная унарная операция dynamic_cast языка C++ позволяет:
 безопасно трансформировать указатель на базовый класс в указатель
на производный класс (с возвратом нулевого указателя при
невозможности выполнения трансформации);
 преобразовывать леводопустимые значения, ссылающиеся на базовый
класс, в ссылки на производный класс (с возбуждением исключения
bad_cast при ошибке).

Единственным операндом dynamic_cast должен являться тип
класса, в котором имеется хотя бы один виртуальный метод.

46
Операция dynamic_cast:
пример (указатели)
// классы Alpha и Beta образуют полиморфную
// иерархию, в которой класс Beta открыто
// наследует классу Alpha

Alpha *al

= new Beta;

if(Beta *bt = dynamic_cast<Beta*>(al)) {
/* успешно */
}
else {
/* неуспешно */
}

47
Операция dynamic_cast:
пример (ссылки)
// классы Alpha и Beta образуют полиморфную
// иерархию, в которой класс Beta открыто
// наследует классу Alpha

#include <typeinfo> // для std::bad_cast
void foo(Alpha &al)
{
/* … */
try {
Beta &bt = dynamic_cast<Beta&>(al))
}
catch(std::bad_cast) {
/* … */
}
}

48
Операция typeid (1 / 2)
Встроенная унарная операция typeid:
 позволяет установить фактический тип выражения-операнда;
 может использоваться с выражениями и именами любых типов (включая
выражения встроенных типов и константы).

Если операнд typeid принадлежит типу класса с одной и более
виртуальными функциями (не указателю на него!), результат
typeid может не совпадать с типом самого выражения.
Операция typeid имеет тип (возвращает значение типа) type_info
и требует подключения заголовочного файла <typeinfo>.

49
Операция typeid (2 / 2)
Реализация класса type_info зависит от компилятора, но в
общем и целом позволяет получить результат в виде
неизменяемой C-строки (const char*), присваивать объекты
type_info друг другу (operator =), а также сравнивать их на
равенство и неравенство (operator ==, operator !=).
#include <typeinfo> // для type_info
Alpha *al = new Alpha;

if(typeid(al) == typeid(Alpha*)) /* … */
if(typeid(*al) == typeid(Alpha)) /* … */

50
Вопросы производительности
 Глубина цепочки наследования не увеличивает затраты
времени и не ограничивает доступ к унаследованным членам
базовых классов.
 Вызов виртуальной функции в большинстве случаев не менее
эффективен, чем косвенный вызов функции по указателю на
нее.
 При использовании встроенных конструкторов глубина
иерархии наследования почти не влияет на
производительность.

 Отмена действия механизма виртуализации, как правило,
необходима по соображениям повышения эффективности.
51
Практикум №4

Постановка задачи
 Реализовать UML-модель как полиморфную иерархию классов
с шаблоном (специализированным шаблоном) класса.
 Дополнить результат иерархией классов исключительных
ситуаций, смоделировать каждую ситуацию и обеспечить ее
корректную обработку.
 Цель — перевести архитектурное описание проекта на языке
UML в исходный программный код на языке C++, отвечающий
заданным критериям полноты и качества результата.

52
Спасибо за внимание
Алексей Петров

Weitere ähnliche Inhalte

Was ist angesagt?

C++ весна 2014 лекция 2
C++ весна 2014 лекция 2C++ весна 2014 лекция 2
C++ весна 2014 лекция 2Technopark
 
C++ осень 2012 лекция 6
C++ осень 2012 лекция 6C++ осень 2012 лекция 6
C++ осень 2012 лекция 6Technopark
 
Java Core. Lecture# 3. Part# 3. Multithreading.
Java Core. Lecture# 3. Part# 3. Multithreading.Java Core. Lecture# 3. Part# 3. Multithreading.
Java Core. Lecture# 3. Part# 3. Multithreading.Anton Moiseenko
 
C# Desktop. Занятие 02.
C# Desktop. Занятие 02.C# Desktop. Занятие 02.
C# Desktop. Занятие 02.Igor Shkulipa
 
C++ Базовый. Занятие 02.
C++ Базовый. Занятие 02.C++ Базовый. Занятие 02.
C++ Базовый. Занятие 02.Igor Shkulipa
 
C# Desktop. Занятие 01.
C# Desktop. Занятие 01.C# Desktop. Занятие 01.
C# Desktop. Занятие 01.Igor Shkulipa
 
Java Core. Lecture# 3. Part# 2. Exceptions.
Java Core. Lecture# 3. Part# 2. Exceptions.Java Core. Lecture# 3. Part# 2. Exceptions.
Java Core. Lecture# 3. Part# 2. Exceptions.Anton Moiseenko
 
Java Core. Lecture# 5. Concurrency.
Java Core. Lecture# 5. Concurrency.Java Core. Lecture# 5. Concurrency.
Java Core. Lecture# 5. Concurrency.Anton Moiseenko
 
Объектно-Ориентированное Программирование на C++, Лекции 1 и 2
Объектно-Ориентированное Программирование на C++, Лекции 1 и 2Объектно-Ориентированное Программирование на C++, Лекции 1 и 2
Объектно-Ориентированное Программирование на C++, Лекции 1 и 2Dima Dzuba
 
C++ STL & Qt. Занятие 03.
C++ STL & Qt. Занятие 03.C++ STL & Qt. Занятие 03.
C++ STL & Qt. Занятие 03.Igor Shkulipa
 
C# Desktop. Занятие 04.
C# Desktop. Занятие 04.C# Desktop. Занятие 04.
C# Desktop. Занятие 04.Igor Shkulipa
 
Объектно-ориентированное программирование. Лекция 7 и 8.
Объектно-ориентированное программирование. Лекция 7 и 8. Объектно-ориентированное программирование. Лекция 7 и 8.
Объектно-ориентированное программирование. Лекция 7 и 8. Dima Dzuba
 
Java Core. Lecture# 3. Part# 1. Abstract classes.
Java Core. Lecture# 3. Part# 1. Abstract classes.Java Core. Lecture# 3. Part# 1. Abstract classes.
Java Core. Lecture# 3. Part# 1. Abstract classes.Anton Moiseenko
 
C++ Базовый. Занятие 04.
C++ Базовый. Занятие 04.C++ Базовый. Занятие 04.
C++ Базовый. Занятие 04.Igor Shkulipa
 
Объектно-Ориентированное Программирование на C++, Лекции 3 и 4
Объектно-Ориентированное Программирование на C++, Лекции  3 и 4 Объектно-Ориентированное Программирование на C++, Лекции  3 и 4
Объектно-Ориентированное Программирование на C++, Лекции 3 и 4 Dima Dzuba
 
C++ STL & Qt. Занятие 10.
C++ STL & Qt. Занятие 10.C++ STL & Qt. Занятие 10.
C++ STL & Qt. Занятие 10.Igor Shkulipa
 
Автоматическая генерация тестов по комментариям к программному коду
Автоматическая генерация тестов по комментариям к программному кодуАвтоматическая генерация тестов по комментариям к программному коду
Автоматическая генерация тестов по комментариям к программному кодуAlexey Noskov
 
C++ STL & Qt. Занятие 09.
C++ STL & Qt. Занятие 09.C++ STL & Qt. Занятие 09.
C++ STL & Qt. Занятие 09.Igor Shkulipa
 
C++ STL & Qt. Занятие 11.
C++ STL & Qt. Занятие 11.C++ STL & Qt. Занятие 11.
C++ STL & Qt. Занятие 11.Igor Shkulipa
 

Was ist angesagt? (20)

C++ весна 2014 лекция 2
C++ весна 2014 лекция 2C++ весна 2014 лекция 2
C++ весна 2014 лекция 2
 
C++ осень 2012 лекция 6
C++ осень 2012 лекция 6C++ осень 2012 лекция 6
C++ осень 2012 лекция 6
 
Java Core. Lecture# 3. Part# 3. Multithreading.
Java Core. Lecture# 3. Part# 3. Multithreading.Java Core. Lecture# 3. Part# 3. Multithreading.
Java Core. Lecture# 3. Part# 3. Multithreading.
 
C# Desktop. Занятие 02.
C# Desktop. Занятие 02.C# Desktop. Занятие 02.
C# Desktop. Занятие 02.
 
Java. Методы
Java. Методы Java. Методы
Java. Методы
 
C++ Базовый. Занятие 02.
C++ Базовый. Занятие 02.C++ Базовый. Занятие 02.
C++ Базовый. Занятие 02.
 
C# Desktop. Занятие 01.
C# Desktop. Занятие 01.C# Desktop. Занятие 01.
C# Desktop. Занятие 01.
 
Java Core. Lecture# 3. Part# 2. Exceptions.
Java Core. Lecture# 3. Part# 2. Exceptions.Java Core. Lecture# 3. Part# 2. Exceptions.
Java Core. Lecture# 3. Part# 2. Exceptions.
 
Java Core. Lecture# 5. Concurrency.
Java Core. Lecture# 5. Concurrency.Java Core. Lecture# 5. Concurrency.
Java Core. Lecture# 5. Concurrency.
 
Объектно-Ориентированное Программирование на C++, Лекции 1 и 2
Объектно-Ориентированное Программирование на C++, Лекции 1 и 2Объектно-Ориентированное Программирование на C++, Лекции 1 и 2
Объектно-Ориентированное Программирование на C++, Лекции 1 и 2
 
C++ STL & Qt. Занятие 03.
C++ STL & Qt. Занятие 03.C++ STL & Qt. Занятие 03.
C++ STL & Qt. Занятие 03.
 
C# Desktop. Занятие 04.
C# Desktop. Занятие 04.C# Desktop. Занятие 04.
C# Desktop. Занятие 04.
 
Объектно-ориентированное программирование. Лекция 7 и 8.
Объектно-ориентированное программирование. Лекция 7 и 8. Объектно-ориентированное программирование. Лекция 7 и 8.
Объектно-ориентированное программирование. Лекция 7 и 8.
 
Java Core. Lecture# 3. Part# 1. Abstract classes.
Java Core. Lecture# 3. Part# 1. Abstract classes.Java Core. Lecture# 3. Part# 1. Abstract classes.
Java Core. Lecture# 3. Part# 1. Abstract classes.
 
C++ Базовый. Занятие 04.
C++ Базовый. Занятие 04.C++ Базовый. Занятие 04.
C++ Базовый. Занятие 04.
 
Объектно-Ориентированное Программирование на C++, Лекции 3 и 4
Объектно-Ориентированное Программирование на C++, Лекции  3 и 4 Объектно-Ориентированное Программирование на C++, Лекции  3 и 4
Объектно-Ориентированное Программирование на C++, Лекции 3 и 4
 
C++ STL & Qt. Занятие 10.
C++ STL & Qt. Занятие 10.C++ STL & Qt. Занятие 10.
C++ STL & Qt. Занятие 10.
 
Автоматическая генерация тестов по комментариям к программному коду
Автоматическая генерация тестов по комментариям к программному кодуАвтоматическая генерация тестов по комментариям к программному коду
Автоматическая генерация тестов по комментариям к программному коду
 
C++ STL & Qt. Занятие 09.
C++ STL & Qt. Занятие 09.C++ STL & Qt. Занятие 09.
C++ STL & Qt. Занятие 09.
 
C++ STL & Qt. Занятие 11.
C++ STL & Qt. Занятие 11.C++ STL & Qt. Занятие 11.
C++ STL & Qt. Занятие 11.
 

Andere mochten auch

C++ осень 2012 лекция 9
C++ осень 2012 лекция 9C++ осень 2012 лекция 9
C++ осень 2012 лекция 9Technopark
 
Черневич Алексей - Обучение языку С++
Черневич Алексей - Обучение языку С++Черневич Алексей - Обучение языку С++
Черневич Алексей - Обучение языку С++Aliaksei Charnevich
 
Обзор библиотеки Boost
Обзор библиотеки BoostОбзор библиотеки Boost
Обзор библиотеки BoostMSU GML VideoGroup
 
C++ осень 2012 лекция 5
C++ осень 2012 лекция 5C++ осень 2012 лекция 5
C++ осень 2012 лекция 5Technopark
 
C++ осень 2013 лекция 1
C++ осень 2013 лекция 1C++ осень 2013 лекция 1
C++ осень 2013 лекция 1Technopark
 
Лекция 11. Вычислительная модель Pregel
Лекция 11. Вычислительная модель PregelЛекция 11. Вычислительная модель Pregel
Лекция 11. Вычислительная модель PregelTechnopark
 

Andere mochten auch (6)

C++ осень 2012 лекция 9
C++ осень 2012 лекция 9C++ осень 2012 лекция 9
C++ осень 2012 лекция 9
 
Черневич Алексей - Обучение языку С++
Черневич Алексей - Обучение языку С++Черневич Алексей - Обучение языку С++
Черневич Алексей - Обучение языку С++
 
Обзор библиотеки Boost
Обзор библиотеки BoostОбзор библиотеки Boost
Обзор библиотеки Boost
 
C++ осень 2012 лекция 5
C++ осень 2012 лекция 5C++ осень 2012 лекция 5
C++ осень 2012 лекция 5
 
C++ осень 2013 лекция 1
C++ осень 2013 лекция 1C++ осень 2013 лекция 1
C++ осень 2013 лекция 1
 
Лекция 11. Вычислительная модель Pregel
Лекция 11. Вычислительная модель PregelЛекция 11. Вычислительная модель Pregel
Лекция 11. Вычислительная модель Pregel
 

Ähnlich wie C++ осень 2013 лекция 4

Java осень 2014 занятие 5
Java осень 2014 занятие 5Java осень 2014 занятие 5
Java осень 2014 занятие 5Technopark
 
Классы и объекты в Java
Классы и объекты в JavaКлассы и объекты в Java
Классы и объекты в Javametaform
 
Классы и объекты в Java
Классы и объекты в JavaКлассы и объекты в Java
Классы и объекты в Javametaform
 
C++ осень 2012 лекция 2
C++ осень 2012 лекция 2C++ осень 2012 лекция 2
C++ осень 2012 лекция 2Technopark
 
C++ осень 2012 лекция 3
C++ осень 2012 лекция 3C++ осень 2012 лекция 3
C++ осень 2012 лекция 3Technopark
 
ук 03.003.01 2011
ук 03.003.01 2011ук 03.003.01 2011
ук 03.003.01 2011etyumentcev
 
паттерны программирования
паттерны программированияпаттерны программирования
паттерны программированияguestfc8ae0
 
Java весна 2013 лекция 9
Java весна 2013 лекция 9Java весна 2013 лекция 9
Java весна 2013 лекция 9Technopark
 
Глава 2: Среда разработки NetBeans
Глава 2: Среда разработки NetBeansГлава 2: Среда разработки NetBeans
Глава 2: Среда разработки NetBeansmetaform
 
Java осень 2012 лекция 9
Java осень 2012 лекция 9Java осень 2012 лекция 9
Java осень 2012 лекция 9Technopark
 
Java осень 2014 занятие 6
Java осень 2014 занятие 6Java осень 2014 занятие 6
Java осень 2014 занятие 6Technopark
 
Dart - светлая сторона силы?
Dart - светлая сторона силы?Dart - светлая сторона силы?
Dart - светлая сторона силы?Mikhail Davydov
 
презентация кметодическим указаниям к лаб. работам
презентация кметодическим указаниям к лаб. работампрезентация кметодическим указаниям к лаб. работам
презентация кметодическим указаниям к лаб. работамstudent_kai
 
Oop java.generics
Oop java.genericsOop java.generics
Oop java.genericsmuqaddas_m
 
C++ Базовый. Занятие 09.
C++ Базовый. Занятие 09.C++ Базовый. Занятие 09.
C++ Базовый. Занятие 09.Igor Shkulipa
 

Ähnlich wie C++ осень 2013 лекция 4 (20)

Классы и объекты С#
Классы и объекты С#Классы и объекты С#
Классы и объекты С#
 
Lecture 3
Lecture 3Lecture 3
Lecture 3
 
Java осень 2014 занятие 5
Java осень 2014 занятие 5Java осень 2014 занятие 5
Java осень 2014 занятие 5
 
Классы и объекты в Java
Классы и объекты в JavaКлассы и объекты в Java
Классы и объекты в Java
 
лек11 5
лек11 5лек11 5
лек11 5
 
лек11 5
лек11 5лек11 5
лек11 5
 
Классы и объекты в Java
Классы и объекты в JavaКлассы и объекты в Java
Классы и объекты в Java
 
C++ осень 2012 лекция 2
C++ осень 2012 лекция 2C++ осень 2012 лекция 2
C++ осень 2012 лекция 2
 
C++ осень 2012 лекция 3
C++ осень 2012 лекция 3C++ осень 2012 лекция 3
C++ осень 2012 лекция 3
 
Doctrine 2
Doctrine 2Doctrine 2
Doctrine 2
 
ук 03.003.01 2011
ук 03.003.01 2011ук 03.003.01 2011
ук 03.003.01 2011
 
паттерны программирования
паттерны программированияпаттерны программирования
паттерны программирования
 
Java весна 2013 лекция 9
Java весна 2013 лекция 9Java весна 2013 лекция 9
Java весна 2013 лекция 9
 
Глава 2: Среда разработки NetBeans
Глава 2: Среда разработки NetBeansГлава 2: Среда разработки NetBeans
Глава 2: Среда разработки NetBeans
 
Java осень 2012 лекция 9
Java осень 2012 лекция 9Java осень 2012 лекция 9
Java осень 2012 лекция 9
 
Java осень 2014 занятие 6
Java осень 2014 занятие 6Java осень 2014 занятие 6
Java осень 2014 занятие 6
 
Dart - светлая сторона силы?
Dart - светлая сторона силы?Dart - светлая сторона силы?
Dart - светлая сторона силы?
 
презентация кметодическим указаниям к лаб. работам
презентация кметодическим указаниям к лаб. работампрезентация кметодическим указаниям к лаб. работам
презентация кметодическим указаниям к лаб. работам
 
Oop java.generics
Oop java.genericsOop java.generics
Oop java.generics
 
C++ Базовый. Занятие 09.
C++ Базовый. Занятие 09.C++ Базовый. Занятие 09.
C++ Базовый. Занятие 09.
 

Mehr von Technopark

Лекция 14. Hadoop в Поиске Mail.Ru
Лекция 14. Hadoop в Поиске Mail.RuЛекция 14. Hadoop в Поиске Mail.Ru
Лекция 14. Hadoop в Поиске Mail.RuTechnopark
 
Лекция 13. YARN
Лекция 13. YARNЛекция 13. YARN
Лекция 13. YARNTechnopark
 
Лекция 12. Spark
Лекция 12. SparkЛекция 12. Spark
Лекция 12. SparkTechnopark
 
Лекция 10. Apache Mahout
Лекция 10. Apache MahoutЛекция 10. Apache Mahout
Лекция 10. Apache MahoutTechnopark
 
Лекция 9. ZooKeeper
Лекция 9. ZooKeeperЛекция 9. ZooKeeper
Лекция 9. ZooKeeperTechnopark
 
Лекция 7. Введение в Pig и Hive
Лекция 7. Введение в Pig и HiveЛекция 7. Введение в Pig и Hive
Лекция 7. Введение в Pig и HiveTechnopark
 
Лекция 6. MapReduce в Hadoop (графы)
Лекция 6. MapReduce в Hadoop (графы)Лекция 6. MapReduce в Hadoop (графы)
Лекция 6. MapReduce в Hadoop (графы)Technopark
 
Лекция 5. MapReduce в Hadoop (алгоритмы)
Лекция 5. MapReduce в Hadoop (алгоритмы)Лекция 5. MapReduce в Hadoop (алгоритмы)
Лекция 5. MapReduce в Hadoop (алгоритмы)Technopark
 
Лекция 4. MapReduce в Hadoop (введение)
Лекция 4. MapReduce в Hadoop (введение)Лекция 4. MapReduce в Hadoop (введение)
Лекция 4. MapReduce в Hadoop (введение)Technopark
 
Лекция 3. Распределённая файловая система HDFS
Лекция 3. Распределённая файловая система HDFSЛекция 3. Распределённая файловая система HDFS
Лекция 3. Распределённая файловая система HDFSTechnopark
 
Лекция 2. Основы Hadoop
Лекция 2. Основы HadoopЛекция 2. Основы Hadoop
Лекция 2. Основы HadoopTechnopark
 
Лекция 1. Введение в Big Data и MapReduce
Лекция 1. Введение в Big Data и MapReduceЛекция 1. Введение в Big Data и MapReduce
Лекция 1. Введение в Big Data и MapReduceTechnopark
 
СУБД 2013 Лекция №10 "Нереляционное решение в области баз данных — NoSQL"
СУБД 2013 Лекция №10 "Нереляционное решение в области баз данных — NoSQL"СУБД 2013 Лекция №10 "Нереляционное решение в области баз данных — NoSQL"
СУБД 2013 Лекция №10 "Нереляционное решение в области баз данных — NoSQL"Technopark
 
СУБД 2013 Лекция №10 "Нереляционное решение в области баз данных — NoSQL" Час...
СУБД 2013 Лекция №10 "Нереляционное решение в области баз данных — NoSQL" Час...СУБД 2013 Лекция №10 "Нереляционное решение в области баз данных — NoSQL" Час...
СУБД 2013 Лекция №10 "Нереляционное решение в области баз данных — NoSQL" Час...Technopark
 
СУБД 2013 Лекция №9 "Безопасность баз данных"
СУБД 2013 Лекция №9 "Безопасность баз данных"СУБД 2013 Лекция №9 "Безопасность баз данных"
СУБД 2013 Лекция №9 "Безопасность баз данных"Technopark
 
СУБД 2013 Лекция №8 "Конфигурирование базы данных"
СУБД 2013 Лекция №8 "Конфигурирование базы данных"СУБД 2013 Лекция №8 "Конфигурирование базы данных"
СУБД 2013 Лекция №8 "Конфигурирование базы данных"Technopark
 
СУБД 2013 Лекция №7 "Оптимизация запросов и индексирование"
СУБД 2013 Лекция №7 "Оптимизация запросов и индексирование"СУБД 2013 Лекция №7 "Оптимизация запросов и индексирование"
СУБД 2013 Лекция №7 "Оптимизация запросов и индексирование"Technopark
 
СУБД 2013 Лекция №5 "Определение узких мест"
СУБД 2013 Лекция №5 "Определение узких мест"СУБД 2013 Лекция №5 "Определение узких мест"
СУБД 2013 Лекция №5 "Определение узких мест"Technopark
 
СУБД 2013 Лекция №6 "Профилирование запросов. Сложноструктурированные SQL-зап...
СУБД 2013 Лекция №6 "Профилирование запросов. Сложноструктурированные SQL-зап...СУБД 2013 Лекция №6 "Профилирование запросов. Сложноструктурированные SQL-зап...
СУБД 2013 Лекция №6 "Профилирование запросов. Сложноструктурированные SQL-зап...Technopark
 
СУБД 2013 Лекция №4 "Расширенные возможности работы с базами данных. Триггеры...
СУБД 2013 Лекция №4 "Расширенные возможности работы с базами данных. Триггеры...СУБД 2013 Лекция №4 "Расширенные возможности работы с базами данных. Триггеры...
СУБД 2013 Лекция №4 "Расширенные возможности работы с базами данных. Триггеры...Technopark
 

Mehr von Technopark (20)

Лекция 14. Hadoop в Поиске Mail.Ru
Лекция 14. Hadoop в Поиске Mail.RuЛекция 14. Hadoop в Поиске Mail.Ru
Лекция 14. Hadoop в Поиске Mail.Ru
 
Лекция 13. YARN
Лекция 13. YARNЛекция 13. YARN
Лекция 13. YARN
 
Лекция 12. Spark
Лекция 12. SparkЛекция 12. Spark
Лекция 12. Spark
 
Лекция 10. Apache Mahout
Лекция 10. Apache MahoutЛекция 10. Apache Mahout
Лекция 10. Apache Mahout
 
Лекция 9. ZooKeeper
Лекция 9. ZooKeeperЛекция 9. ZooKeeper
Лекция 9. ZooKeeper
 
Лекция 7. Введение в Pig и Hive
Лекция 7. Введение в Pig и HiveЛекция 7. Введение в Pig и Hive
Лекция 7. Введение в Pig и Hive
 
Лекция 6. MapReduce в Hadoop (графы)
Лекция 6. MapReduce в Hadoop (графы)Лекция 6. MapReduce в Hadoop (графы)
Лекция 6. MapReduce в Hadoop (графы)
 
Лекция 5. MapReduce в Hadoop (алгоритмы)
Лекция 5. MapReduce в Hadoop (алгоритмы)Лекция 5. MapReduce в Hadoop (алгоритмы)
Лекция 5. MapReduce в Hadoop (алгоритмы)
 
Лекция 4. MapReduce в Hadoop (введение)
Лекция 4. MapReduce в Hadoop (введение)Лекция 4. MapReduce в Hadoop (введение)
Лекция 4. MapReduce в Hadoop (введение)
 
Лекция 3. Распределённая файловая система HDFS
Лекция 3. Распределённая файловая система HDFSЛекция 3. Распределённая файловая система HDFS
Лекция 3. Распределённая файловая система HDFS
 
Лекция 2. Основы Hadoop
Лекция 2. Основы HadoopЛекция 2. Основы Hadoop
Лекция 2. Основы Hadoop
 
Лекция 1. Введение в Big Data и MapReduce
Лекция 1. Введение в Big Data и MapReduceЛекция 1. Введение в Big Data и MapReduce
Лекция 1. Введение в Big Data и MapReduce
 
СУБД 2013 Лекция №10 "Нереляционное решение в области баз данных — NoSQL"
СУБД 2013 Лекция №10 "Нереляционное решение в области баз данных — NoSQL"СУБД 2013 Лекция №10 "Нереляционное решение в области баз данных — NoSQL"
СУБД 2013 Лекция №10 "Нереляционное решение в области баз данных — NoSQL"
 
СУБД 2013 Лекция №10 "Нереляционное решение в области баз данных — NoSQL" Час...
СУБД 2013 Лекция №10 "Нереляционное решение в области баз данных — NoSQL" Час...СУБД 2013 Лекция №10 "Нереляционное решение в области баз данных — NoSQL" Час...
СУБД 2013 Лекция №10 "Нереляционное решение в области баз данных — NoSQL" Час...
 
СУБД 2013 Лекция №9 "Безопасность баз данных"
СУБД 2013 Лекция №9 "Безопасность баз данных"СУБД 2013 Лекция №9 "Безопасность баз данных"
СУБД 2013 Лекция №9 "Безопасность баз данных"
 
СУБД 2013 Лекция №8 "Конфигурирование базы данных"
СУБД 2013 Лекция №8 "Конфигурирование базы данных"СУБД 2013 Лекция №8 "Конфигурирование базы данных"
СУБД 2013 Лекция №8 "Конфигурирование базы данных"
 
СУБД 2013 Лекция №7 "Оптимизация запросов и индексирование"
СУБД 2013 Лекция №7 "Оптимизация запросов и индексирование"СУБД 2013 Лекция №7 "Оптимизация запросов и индексирование"
СУБД 2013 Лекция №7 "Оптимизация запросов и индексирование"
 
СУБД 2013 Лекция №5 "Определение узких мест"
СУБД 2013 Лекция №5 "Определение узких мест"СУБД 2013 Лекция №5 "Определение узких мест"
СУБД 2013 Лекция №5 "Определение узких мест"
 
СУБД 2013 Лекция №6 "Профилирование запросов. Сложноструктурированные SQL-зап...
СУБД 2013 Лекция №6 "Профилирование запросов. Сложноструктурированные SQL-зап...СУБД 2013 Лекция №6 "Профилирование запросов. Сложноструктурированные SQL-зап...
СУБД 2013 Лекция №6 "Профилирование запросов. Сложноструктурированные SQL-зап...
 
СУБД 2013 Лекция №4 "Расширенные возможности работы с базами данных. Триггеры...
СУБД 2013 Лекция №4 "Расширенные возможности работы с базами данных. Триггеры...СУБД 2013 Лекция №4 "Расширенные возможности работы с базами данных. Триггеры...
СУБД 2013 Лекция №4 "Расширенные возможности работы с базами данных. Триггеры...
 

C++ осень 2013 лекция 4

  • 2. Лекция №4. Специальные вопросы наследования и полиморфизма 1. Инициализация, копирование, преобразование и уничтожение объектов (продолжение). Идиома RAII. 2. Раннее и позднее связывание. Перегрузка и перекрытие членов класса. 3. Виртуальные функции. Абстрактные классы. Множественное и виртуальное наследование. 4. RTTI и операции приведения типов. Производительность и безопасность полиморфизма и средств поддержки RTTI. 5. Постановка задач к практикуму №4. 2
  • 3. Инициализация без конструктора (1 / 2) Класс, все члены которого открыты, может задействовать механизм явной позиционной инициализации, ассоциирующий значения в списке инициализации с членами данных в соответствии с их порядком. class Test { public: int int_prm; double dbl_prm; string str_prm; }; // … Test test = { 1, -3.14, "dictum factum" }; 3
  • 4. Инициализация без конструктора (2 / 2) Преимуществами такой техники выступают:  скорость и эффективность, особо значимые при выполнении во время запуска программы (для глобальных объектов). Недостатками инициализации без конструктора являются:  пригодность только для классов, члены которых открыты;  отсутствие поддержки инкапсуляции и абстрактных типов;  требование предельной точности и аккуратности в применении. 4
  • 5. Конструкторы по умолчанию (1 / 2) Конструктор по умолчанию не требует задания значений его параметров, хотя таковые могут присутствовать в сигнатуре. class Test { public: Test(int ipr = 0, double dpr = 0.0); /* … */ }; Наличие формальных параметров в конструкторе по умолчанию позволяет сократить общее число конструкторов и объем исходного кода. 5
  • 6. Конструкторы по умолчанию (2 / 2) Если в классе определен хотя бы один конструктор с параметрами, то при использовании класса со стандартными контейнерами и динамическими массивами экземпляров конструктор по умолчанию обязателен. Test *tests = new Test[TEST_PLAN_SIZE]; Если конструктор по умолчанию не определен, но существует хотя бы один конструктор с параметрами, в определении объектов должны присутствовать аргументы. Если ни одного конструктора не определено, объект класса не инициализируется (память под статическими объектами по общим правилам обнуляется). 6
  • 7. Конструкторы с параметрами: пример class Test { public: Test(int prm) : _prm (prm) {} private: int _prm; }; // все вызовы конструктора допустимы и эквивалентны Test test1(10), test2 = Test(10), test3 = 10; // для одного аргумента 7
  • 8. Массивы объектов: пример // массивы объектов класса определяются // аналогично массивам объектов базовых типов // для конструктора с одним аргументом Test testplan1[] = { 10, -5, 0, 127 }; // для конструктора с несколькими аргументами Test testplan2[5] = { Test(10, 0.1), Test(-5, -3.6), Test(0, 0.0), Test() // если есть конструктор по умолчанию }; 8
  • 9. Закрытые и защищенные конструкторы Описание конструктора класса как защищенного или закрытого дает возможность ограничить или полностью запретить отдельные способы создания объектов класса. В большинстве случаев закрытые и защищенные конструкторы используются для:  предотвращения копирования одного объекта в другой;  указания на то, что конструктор должен вызываться только для создания подобъектов базового класса в объекте производного класса, а не создания объектов, непосредственно доступных в коде программы. 9
  • 10. Почленная инициализация и присваивание (1 / 2) Почленная инициализация по умолчанию — механизм инициализации одного объекта класса другим объектом того же класса, который активизируется независимо от наличия в определении класса явного конструктора. Почленная инициализация по умолчанию происходит в следующих ситуациях:  явная инициализация одного объекта другим;  передача объекта класса в качестве аргумента функции;  передача объекта класса в качестве возвращаемого функцией значения;  определение непустого стандартного последовательного контейнера;  вставка объекта класса в стандартный контейнер. 10
  • 11. Почленная инициализация и присваивание (2 / 2) Почленная инициализация по умолчанию подавляется при наличии в определении класса конструктора копирования. Запрет почленной инициализации по умолчанию осуществляется одним из следующих способов:  описание закрытого конструктора копирования (не действует для методов класса и дружественных объектов);  описание конструктора копирования без его определения (действует всюду). Почленное присваивание по умолчанию — механизм присваивания одному объекту класса значения другого объекта того же класса, отличный от почленной инициализации по умолчанию использованием копирующей операции-функции присваивания вместо конструктора копирования. 11
  • 12. Конструкторы копирования Конструктор копирования принимает в качестве единственного параметра константную ссылку на существующий объект класса. В случае отсутствия явного конструктора копирования в определении класса производится почленная инициализация объекта по умолчанию. class Test { /* … */ Test(const Test &other); /* … */ }; 12
  • 13. Конструкторы и операции преобразования Конструкторы преобразования служат для построения объектов класса по одному или нескольким значениям иных типов. Операции преобразования позволяют преобразовывать содержимое объектов класса к требуемым типам данных. class Test { // конструкторы преобразования Test(const char *); Test(const string &); // операции преобразования operator int () { return int_prm; } operator double () { return dbl_prm; } /* … */ }; 13
  • 14. Деструкторы. Виртуальные деструкторы (1 / 2) Деструктор — не принимающий параметров и не возвращающий результат метод класса, автоматически вызываемый при выходе объекта из области видимости и применении к указателю на объект класса операции delete. class Test { /* … */ virtual ~Test(); }; Примечание: деструктор не вызывается при выходе из области видимости ссылки или указателя на объект. 14
  • 15. Деструкторы. Виртуальные деструкторы (2 / 2) Типичные задачи деструктора:  сброс содержимого программных буферов в долговременные хранилища;  освобождение (возврат) системных ресурсов, главным образом — оперативной памяти;  закрытие файлов или устройств;  снятие блокировок, останов таймеров и т.д. Для обеспечения корректного освобождения ресурсов объектами производных классов деструкторы в иерархиях, как правило, определяют как виртуальные. 15
  • 16. Идиома RAII Закрепление за конструкторами функции захвата, выделения, блокировки или инициализации ресурсов, а за деструкторами — функции их возврата, освобождения и снятия установленных блокировок:  позволяет безопасно обрабатывать ошибки и исключения;  составляет суть одной из важнейших идиом ОО-программирования RAII (англ. Resource Acquisition Is Initialization — «получение ресурса есть инициализация»). Работа идиомы RAII в языке C++ основана, главным образом, на гарантированном вызове деструкторов автоматических переменных, являющихся экземплярами классов, при выходе из соответствующих областей видимости. 16
  • 17. Явный вызов деструкторов Потребность в явном вызове деструктора обычно связана с необходимостью уничтожить динамически размещенный объект без освобождения памяти. char *buf = new char[sizeof(Test)]; // "размещающий" вариант new Test *ptc = new (buf) Test(100); /* … */ ptc->~Test(); // вызов 1 Test *ptc = new (buf) Test(200); /* … */ ptc->~Test(); // вызов 2 delete [] buf; 17
  • 18. Список инициализации в конструкторе Выполнение любого конструктора состоит из двух фаз:  фаза явной (неявной) инициализации (обработка списка инициализации) — предполагает начальную инициализацию членов данных;  фаза вычислений (исполнение тела конструктора) — предполагает присваивание значений (в предварительно инициализированных областях памяти). Присваивание значений членам данных – объектам классов в теле конструктора неэффективно ввиду ранее произведенной инициализации по умолчанию. Присваивание значений членам данных, представляющих базовые типы, по эффективности равнозначно инициализации. К началу исполнения тела конструктора все константные члены и члены-ссылки должны быть инициализированы. 18
  • 19. Семантика переноса (C++11) Введение в С++11 семантики переноса (англ. move semantics) обогащает язык возможностями более тонкого и эффективного управления памятью данных, устраняющего копирование объектов там, где оно нецелесообразно. Технически семантика переноса реализуется при помощи ссылок на праводопустимые выражения и конструкторов переноса. Конструкторы переноса не создают точную копию своего параметра, а перенастраивают параметр так, чтобы права владения соответствующей областью памяти были переданы вновь создаваемому объекту («заимствованы» последним). Аналогично работают операции присваивания с переносом. 19
  • 20. Конструктор переноса: пример (1 / 2) class Alpha { public: Alpha(); Alpha(const Alpha &a); // конструктор копирования Alpha(Alpha &&a); // конструктор переноса ~Alpha(); private: size_t sz; double *d; }; Alpha::Alpha() : sz(0), d(0) { } Alpha::~Alpha() { delete [] d; } 20
  • 21. Конструктор переноса: пример (2 / 2) // конструктор копирования Alpha::Alpha(const Alpha &a) : sz(a.sz) { d = new double[sz]; /* … */ for(size_t i = 0; i < sz; i++) d[i] = a.d[i]; } // конструктор переноса Alpha::Alpha(Alpha &&a) : sz(a.sz) { d = a.d; // перенастройка параметра a.d = nullptr; // C++11 a.sz = 0; } 21
  • 22. Наследование: ключевые понятия Наследование содействует повторному использованию атрибутов и методов класса, а значит, делает процесс разработки ПО более эффективным. Возникающие между классами A и B отношения наследования позволяют, например, говорить, что:  класс A является базовым (родительским) классом, классом-предком, надклассом (англ. superclass);  класс B является производным (дочерним) классом, классом-потомком, подклассом (англ. subclass). Отношения наследования связывают классы в иерархию наследования, вид которой зависит от числа базовых классов у каждого производного:  при одиночном наследовании иерархия имеет вид дерева;  при множественном наследовании — вид направленного ациклического графа (НАГ) произвольного вида. 22
  • 23. Наследование: примеры (UML) Одиночное наследование (слева), множественное наследование (в центре, классы Alpha и Alpha (II) идентичны), виртуальное множественное наследование (справа) 23
  • 24. Полиморфизм подклассов В том случае если базовый и производный классы имеют общий открытый интерфейс, говорят, что производный класс представляет собой подкласс базового. Отношение между классом и подклассом, позволяющее указателю или ссылке на базовый класс без вмешательства программиста адресовать объект производного класса, возникает в C++ благодаря поддержке полиморфизма. Полиморфизм позволяет предложить такую реализацию ядра объектно-ориентированного приложения, которая не будет зависеть от конкретных используемых подклассов. 24
  • 25. Раннее и позднее связывание В рамках классического объектного подхода, — а равно и процедурного программирования, — адрес вызываемой функции (метода класса) определяется на этапе компиляции (сборки). Такой порядок связывания вызова функции и ее адреса получил название раннего (статического). Позднее (динамическое) связывание состоит в нахождении (разрешении) нужной функции во время исполнения кода. При этом работа по разрешению типов перекладывается с программиста на компилятор. В языке C++ динамическое связывание поддерживается механизмом виртуальных методов класса, для работы с которыми компиляторы строят таблицы виртуальных методов (англ. VMT, virtual method table). 25
  • 26. Базовые и производные классы ОО-проектирование допускает существование классов, которые могут выполнять чисто технические функции, моделировать абстрактные сущности и отличаться функциональной неполнотой: • не подлежащий реализации в виде экземпляров (объектов) базовый класс может оставаться абстрактным. В противовес абстрактным базовым классам классы, предполагающие создание экземпляров, именуют конкретными; • (абстрактные) базовые классы специфицируют открытые интерфейсы иерархий и содержат общие для всех подклассов атрибуты и методы (или их прототипы). Множество подклассов любого базового класса ограничено иерархией наследования, но потенциально бесконечно (ввиду отсутствия пределов по расширению иерархии вглубь и вширь). 26
  • 27. Определение наследования Определение отношения наследования имеет вид (для одиночного наследования): // заголовок класса class <имя производного класса> : <уровень доступа> <имя базового класса> // тело класса { /* … */ }; где <уровень доступа> — ключевое слово public, private или protected, а <имя базового класса> — имя ранее определенного (не описанного!) класса. В зависимости от уровня доступа к членам базового класса говорят об открытом, закрытом или защищенном наследовании. 27
  • 28. Определение наследования: пример // описание производного класса // (не включает список базовых классов!) class Deposit; /* … */ // определения классов class Account { /* … */ }; class Deposit : public Account { /* … */ }; 28
  • 29. Защищенные и закрытые члены класса Атрибуты и методы базового класса, как правило, должны быть непосредственно доступны для производных классов и непосредственно недоступны для прочих компонентов программы. В этом случае они помещаются в секцию protected, в результате чего защищенные члены данных и методы базового класса:  доступны производному классу (прямому потомку);  недоступны классам вне рассматриваемой иерархии, глобальным функциям и вызывающей программе. Если наличие прямого доступа к члену класса со стороны производных классов нежелательно, он вводится как закрытый. Закрытые члены класса не наследуются потомками. Для доступа к ним класс-потомок должен быть объявлен в классе-предке как дружественный. Отношения дружественности не наследуются. 29
  • 30. Перегрузка и перекрытие членов класса Члены данных базового класса могут перекрываться одноименными членами данных производного класса, при этом их типы не должны обязательно совпадать. (Для доступа к члену базового класса его имя должно быть квалифицировано.) Методы базового и производного классов не образуют множество перегруженных функций. В этом случае методы производного класса не перегружают (англ. overload), а перекрывают (англ. override) методы базового. Для явного создания объединенного множества перегруженных функций базового и производного классов используется объявление using, которое вводит именованный член базового класса в область видимости производного. 30
  • 31. Перегрузка и перекрытие членов класса: пример Примечание: в область видимости производного класса попадают все одноименные методы базового класса, а не только некоторые из них. class Account { /* … */ void display(const char *fmt); void display(const int mode = 0); }; class Deposit : public Account { void display(const string &fmt); using Account::display; /* … */ }; 31
  • 32. Порядок вызова конструкторов производных классов (1 / 2) Порядок вызова конструкторов объектов-членов, а также базовых классов при построении объекта производного класса не зависит от порядка их перечисления в списке инициализации конструктора производного класса и является следующим:  конструктор базового класса (если таковых несколько, конструкторы вызываются в порядке перечисления имен классов в списке базовых классов);  конструктор объекта-члена (если таковых несколько, конструкторы вызываются в порядке объявления членов данных в определении класса);  конструктор производного класса. 32
  • 33. Порядок вызова конструкторов производных классов (2 / 2) Конструктор производного класса может вызывать конструкторы классов, непосредственно являющихся базовыми для данного (прямых предков), и — без учета виртуального наследования — только их. Примечание: правильно спроектированный конструктор производного класса не должен инициализировать атрибуты базового класса напрямую (путем присваивания значений). 33
  • 34. Список инициализации при наследовании: пример class Alpha { public: // Alpha(); Alpha(int i); /* … */ }; class Beta : public Alpha { public: Beta() : _s("dictum factum") { } // Beta() : Alpha(), _s("dictum factum") { } Beta(int i, string s) : Alpha(i), _s(s) { } protected: string _s; /* … */ }; 34
  • 35. Порядок вызова деструкторов производных классов Порядок вызова деструкторов при уничтожении объекта производного класса прямо противоположен порядку вызова конструкторов и является следующим:  деструктор производного класса;  деструктор объекта-члена (или нескольких);  деструктор базового класса (или нескольких). Взаимная противоположность порядка вызова конструкторов и деструкторов является строгой гарантией языка C++. 35
  • 36. Виртуальные функции (1 / 2) Методы, результат разрешения вызова которых зависит от «реального» (динамического) типа объекта, доступного по указателю или ссылке, называются виртуальными и при определении в базовом классе снабжаются спецификатором virtual. Примечание: в этом контексте тип непосредственно определяемого экземпляра, ссылки или указателя на объект называется статическим. Для самого объекта любого типа (автоматической переменной) статический и динамический тип совпадают. По умолчанию объектная модель C++ работает с невиртуальными методами. Механизм виртуальных функций работает только в случае косвенной адресации (по указателю или ссылке). 36
  • 37. Виртуальные функции (2 / 2) Значения формальных параметров виртуальных функций определяются (а) на этапе компиляции (б) типом объекта, через который осуществляется вызов. Отмена действия механизма виртуализации возможна и достигается статическим вызовом метода при помощи операции разрешения области видимости (::). class Alpha { /* … */ virtual void display(); }; class Beta : public Alpha { void display(); } 37
  • 38. Чистые виртуальные функции Класс, где виртуальный метод объявляется впервые, должен определять его тело либо декларировать метод как не имеющую собственной реализации чистую виртуальную функцию. Производный класс может наследовать реализацию виртуального метода из базового класса или перекрывать его собственной реализацией, при этом прототипы обеих реализаций обязаны совпадать. virtual void display() = 0; Примечание: единственное исключение С++ делает для возвращаемого значения. Значение, возвращаемое реализацией в производном классе, может иметь тип, открыто наследующий классу значения, возвращаемого реализацией в базовом. 38
  • 39. Абстрактные классы Класс, который определяет или наследует хотя бы одну чистую виртуальную функцию, является абстрактным. Экземпляры абстрактных классов создавать нельзя. Абстрактный класс может реализовываться только как подобъект производного, неабстрактного класса. Чистые виртуальные функции могут иметь тело, вызов которого, впрочем, может производиться только статически (при помощи операции разрешения области видимости), но не динамически (при помощи механизма виртуализации). 39
  • 40. Чистые виртуальные функции и абстрактные классы: пример // class Alpha; // class Beta : public Alpha; virtual void Alpha::display() { /* … */ }; void Beta::display() { // вызов чистой виртуальной функции Alpha::display(); /* … */ } 40
  • 41. Множественное наследование Множественное наследование в ООП — это наследование от двух и более базовых классов, возможно, с различным уровнем доступа. Язык C++ не накладывает ограничений на количество базовых классов. При множественном наследовании конструкторы базовых классов вызываются в порядке перечисления имен классов в списке базовых классов. Порядок вызова деструкторов ему прямо противоположен. Унаследованные от разных базовых классов методы не образуют множество перегруженных функций, а потому разрешаются только по имени, без учета их сигнатур. 41
  • 42. Виртуальное наследование При множественном наследовании возможна ситуация неоднократного включения подобъекта одного и того же базового класса в состав производного. Связанные с нею проблемы и неоднозначности снимает виртуальное наследование. Суть виртуального наследования — включение в состав класса единственного разделяемого подобъекта базового класса (виртуального базового класса). Виртуальное наследование не характеризует базовый класс, а лишь описывает его отношение к производному. Использование виртуального наследования должно быть взвешенным проектным решением конкретных проблем объектноориентированного проектирования. 42
  • 43. Конструкция объектов при виртуальном наследовании Виртуальные базовые классы конструируются перед невиртуальными независимо от их расположения в иерархии наследования. Ответственность за инициализацию виртуального базового класса несет на себе ближайший (финальный) производный класс. В промежуточных производных классах прямые вызовы конструкторов виртуальных базовых классов автоматически подавляются. 43
  • 44. Множественное и виртуальное наследование: пример // множественное наследование class Alpha { /* … */ }; class Beta : public Alpha { /* … */ }; class Gamma { /* … */ }; class Delta : public Beta, public Gamma { /* … */ }; // виртуальное наследование class Alpha { /* … */ }; class Beta : virtual public Alpha // то же: class Beta : public virtual Alpha { /* … */ }; 44
  • 45. Динамическая идентификация типов времени выполнения (RTTI) Динамическая идентификация типов времени выполнения (англ. Real-Time Type Identification) обеспечивает специальную поддержку полиморфизма и позволяет программе узнать реальный производный тип объекта, адресуемого по ссылке или по указателю на базовый класс. Поддержка RTTI в C++ реализована двумя операциями:  операция dynamic_cast поддерживает преобразование типов времени выполнения;  операция typeid идентифицирует реальный тип выражения. Операции RTTI — это события времени выполнения для классов с виртуальными функциями и события времени компиляции для остальных типов. Исследование RTTI-информации полезно, в частности, при решении задач системного программирования. 45
  • 46. Операция dynamic_cast Встроенная унарная операция dynamic_cast языка C++ позволяет:  безопасно трансформировать указатель на базовый класс в указатель на производный класс (с возвратом нулевого указателя при невозможности выполнения трансформации);  преобразовывать леводопустимые значения, ссылающиеся на базовый класс, в ссылки на производный класс (с возбуждением исключения bad_cast при ошибке). Единственным операндом dynamic_cast должен являться тип класса, в котором имеется хотя бы один виртуальный метод. 46
  • 47. Операция dynamic_cast: пример (указатели) // классы Alpha и Beta образуют полиморфную // иерархию, в которой класс Beta открыто // наследует классу Alpha Alpha *al = new Beta; if(Beta *bt = dynamic_cast<Beta*>(al)) { /* успешно */ } else { /* неуспешно */ } 47
  • 48. Операция dynamic_cast: пример (ссылки) // классы Alpha и Beta образуют полиморфную // иерархию, в которой класс Beta открыто // наследует классу Alpha #include <typeinfo> // для std::bad_cast void foo(Alpha &al) { /* … */ try { Beta &bt = dynamic_cast<Beta&>(al)) } catch(std::bad_cast) { /* … */ } } 48
  • 49. Операция typeid (1 / 2) Встроенная унарная операция typeid:  позволяет установить фактический тип выражения-операнда;  может использоваться с выражениями и именами любых типов (включая выражения встроенных типов и константы). Если операнд typeid принадлежит типу класса с одной и более виртуальными функциями (не указателю на него!), результат typeid может не совпадать с типом самого выражения. Операция typeid имеет тип (возвращает значение типа) type_info и требует подключения заголовочного файла <typeinfo>. 49
  • 50. Операция typeid (2 / 2) Реализация класса type_info зависит от компилятора, но в общем и целом позволяет получить результат в виде неизменяемой C-строки (const char*), присваивать объекты type_info друг другу (operator =), а также сравнивать их на равенство и неравенство (operator ==, operator !=). #include <typeinfo> // для type_info Alpha *al = new Alpha; if(typeid(al) == typeid(Alpha*)) /* … */ if(typeid(*al) == typeid(Alpha)) /* … */ 50
  • 51. Вопросы производительности  Глубина цепочки наследования не увеличивает затраты времени и не ограничивает доступ к унаследованным членам базовых классов.  Вызов виртуальной функции в большинстве случаев не менее эффективен, чем косвенный вызов функции по указателю на нее.  При использовании встроенных конструкторов глубина иерархии наследования почти не влияет на производительность.  Отмена действия механизма виртуализации, как правило, необходима по соображениям повышения эффективности. 51
  • 52. Практикум №4 Постановка задачи  Реализовать UML-модель как полиморфную иерархию классов с шаблоном (специализированным шаблоном) класса.  Дополнить результат иерархией классов исключительных ситуаций, смоделировать каждую ситуацию и обеспечить ее корректную обработку.  Цель — перевести архитектурное описание проекта на языке UML в исходный программный код на языке C++, отвечающий заданным критериям полноты и качества результата. 52