Углубленное
программирование
на языке C++
Алексей Петров
Лекция №3. Специальные
вопросы инкапсуляции
1. Определение и состав класса.
Работа с членами класса и
указателями на них.
2. Дружественные классы и
функции.
3. Вложенные типы.
4. Инициализация, копирование,
преобразование и уничтожение
объектов.
5. Инкапсуляция и вопросы
производительности.

6. Постановка задач
к практикуму №3.
2
Инкапсуляция — базовый принцип ООП
Инкапсуляция, или сокрытие реализации, является фундаментом
объектного подхода к разработке ПО.
• Следуя данному подходу, программист рассматривает задачу в терминах
предметной области, а создаваемый им продукт видит как совокупность
абстрактных сущностей — классов (в свою очередь формально
являющихся пользовательскими типами).
• Инкапсуляция предотвращает прямой доступ к внутреннему
представлению класса из других классов и функций программы.
• Без нее теряют смысл остальные основополагающие принципы объектноориентированного программирования (ООП): наследование и полиморфизм.
Сущность инкапсуляции можно отразить формулой:
Открытый интерфейс + скрытая реализация
3
Класс: в узком или широком смысле?
Принцип инкапсуляции распространяется не только на классы
(class), но и на структуры (struct), а также объединения (union).
Это связано с расширительным толкованием понятия «класс» в
языке C++, трактуемом как в узком, так и широком смысле:
• класс в узком смысле — одноименный составной пользовательский тип
данных, являющийся контейнером для данных и алгоритмов их обработки.
Вводится в текст программы определением типа со спецификатором class;

• класс в широком смысле — любой составной пользовательский тип данных,
агрегирующий данные и алгоритмы их обработки. Вводится в текст
программы определением типа с одним из спецификаторов struct, union или
class.

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

4
Определение класса: пример

// пустой класс
class Document { };
// непустой класс
class Book {
public:
Book();
private:
string _author, _title;
};

5
Описание класса
Описание класса вида
<спецификатор класса> <имя класса>;

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

В случае если класс описан, но не определен, запрещается:





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

// описание класса
class Account;

// допустимо

// определения объектов:
Account *pAcc = NULL;
// допустимо
void foo(const Account *pA); // допустимо
class Account acc;

// недопустимо

7
Объект класса
Выделение памяти под объект (экземпляр) класса происходит при
определении такого объекта, ссылки на объект или указателя на
него. Объект класса:
• имеет размер, достаточный для размещения в нем всех (нестатических)
атрибутов, собственную копию каждого из которых имеет каждый
индивидуальный объект;
• характеризуется областью видимости и обладает временем жизни.

Объекты одного класса могут присваиваться друг другу. В
отсутствие в определении класса конструктора копирования
копирование объектов эквивалентно копированию атрибутов по
правилам копирования значений их типов. Будучи параметром или
возвращаемым значением функции, объект класса передается
через стек по значению.
8
Объект класса: пример

// определение класса (и объекта — допустимо)
class Account { /* … */ };
class Deposit { /* … */ } deposit;
// определения объектов: допустимо
class Account acc;
Account *pAcc = new Account(100);
Account &rAcc = acc;
class Account *&prAcc = pAcc;
// определения объектов: недопустимо
Account &rAcc2 = &acc;

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

10
Константный объект класса (2 / 2)
Неизменность членов-данных, являющихся указателями,
распространяется только на их значение (адрес) и не
распространяется на содержимое областей памяти, которые они
адресуют.
Примечание: Модификация адресуемых таким образом областей
памяти демонстрирует «плохой стиль» программирования
Например:
const Document myDocument;

11
Состав класса: атрибуты
За содержательную сторону класса на языке C++ отвечают
входящие в него атрибуты (члены данных):
 статические (со спецификатором static):
 в том числе константные (со спецификатором const);
 неустойчивые (со спецификатором volatile);
 изменчивые (со спецификатором mutable);
 прочие (без формальных спецификаторов).

12
Состав класса: методы
За алгоритмическую сторону класса на языке C++ отвечают
входящие в него методы (функции-члены), в том числе
специальные (конструкторы и деструкторы):






встроенные (со спецификатором inline);
константные (со спецификатором const);
статические (со спецификатором static);
неустойчивые (со спецификатором volatile);
прочие (без формальных спецификаторов).

13
Состав класса: прочие элементы
В состав класса на языке C++, помимо атрибутов и методов, могут
входить следующие прочие элементы:
 описания дружественных объектов:
 прототипы дружественных функций;
 описания дружественных классов;
 определения типов;
 битовые поля;
 вложенные классы.

14
Нестатические члены данных
За содержательную сторону класса ответственны его атрибуты.
Чаще всего каждый экземпляр (объект) класса имеет свой набор
нестатических атрибутов.
Нестатические члены данных сопоставляются с конкретным
экземпляром класса и тиражируются. Время жизни такого члена
данных равно времени жизни объекта. Нестатические члены
данных нельзя инициализировать в теле класса.
Для обращения к нестатическим членам данных служат операции
доступа (. или ->), левым операндом которых выступает
леводопустимое выражение: идентификатор объекта, ссылка или
указатель на объект (допустимый вариант — this, см. далее).
15
Нестатические члены данных: пример

class Book
{
/* … */
int
_pages;
string
_title;
vector<string> _chapTitles;
/* … */
} book;

Book *pBook = &book;
/* … */
book._pages = 100;
// эквивалентно: pBook->_pages = 100;
// эквивалентно: (*pBook)._pages = 100;

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

 на статические члены распространяется действие спецификаторов
доступа.
17
Статические члены данных (2 / 2)
Обычно статический член инициализируется вне определения
класса. Определение статического члена данных в программе
может быть лишь одно. Для обращения к статическому члену
класса могут использоваться:
• операция доступа с леводопустимым выражением;
• операция разрешения области видимости с именем класса в качестве левого
операнда.

Примечание: В качестве исключения константный статический член
целого типа может быть инициализирован в теле класса. В этом
случае он трактуется как именованная константа.
Статический член данных может иметь тот же тип класса, членом
которого он является, а также быть аргументом по умолчанию для
его метода.
18
Статические члены данных: пример

class BinaryTree
{
/* … */
static char
static const short
static const char
};

delimiter;
base = 10;
*_format;

char BinaryTree::delimiter = ',';
const char *BinaryTree::_format = "(%d) %d,_";
BinaryTree tree;
// ...
tree.delimiter = ' ';
BinaryTree::delimiter = ';';
19
Неустойчивые объекты (1 / 2)
Неустойчивые, или асинхронно изменяемые (volatile), объекты
могут изменяться незаметно для компилятора.
Пример: Переменная, обновляемая значением системных часов или
значением, полученным через системный порт.
Целью определения объекта как неустойчивого является
информирование компилятора о том, что тот не может определить,
каким образом может изменяться значение данного объекта.
Спецификатор volatile сообщает компилятору о том, что при
работе с данным объектом не следует выполнять оптимизацию
кода.

20
Неустойчивые объекты (2 / 2)
Допустимы неустойчивые объекты скалярных и составных типов,
указатели на неустойчивые объекты, неустойчивые массивы:
 в неустойчивом массиве неустойчивым считается каждый элемент;
 в неустойчивом экземпляре (объекте) класса неустойчивым считается
каждый член данных. Объекты классов неустойчивы целиком.

Например:
volatile unsigned long timer;// неустойчивый скаляр
volatile short ports[size]; // неустойчивый массив
// указатель на неустойчивый объект класса
volatile Timer *tmr;

Для преобразования неустойчивого типа в устойчивый
используется const_cast.
21
Изменчивые члены данных
Атрибуты класса, допускающие модификацию при любом
использовании объекта, должны определяться как изменчивые.
Изменчивые атрибуты не являются константными, даже будучи
членами константного объекта, что позволяет модифицировать их
значения, в том числе константными методами.
Например:
class Book
{
/* ... */
mutable int _currentPage;
/* ... */
void locate(const int &value) const
{ /* ... */ _currentPage = value; /* ... */ }
};
22
Указатель this
Указатель this — неявно определяемый константный указатель
на объект класса, через который происходит вызов
соответствующего нестатического метода.
Для неконстантных методов класса T имеет тип T *const, для
константных — имеет тип const T *const, для неустойчивых —
volatile T *const. Указатель this допускает разыменование (*this).
Применение this внутри методов допустимо, но чаще всего
излишне. Исключение составляют две ситуации:
 сравнение адресов объектов:
if (this != someObj) /* … */
 оператор return:
return *this;
23
Нестатические методы класса
За поведение реализованной в виде класса абстракции отвечают
функции-члены (методы). В отличие от атрибутов, методы класса
существуют в единственном экземпляре, причем даже тогда, когда
ни один объект класса не существует.
Подавляющее большинство методов класса оперирует
нестатическими атрибутами и в этом смысле может условно
именоваться нестатическими методами.
Для методов произвольного класса справедливо следующее:
 методы класса имеют доступ ко всем атрибутам класса;
 методы класса могут перегружать другие методы того же класса;
 нестатические методы класса получают в свое распоряжение указатель
this.
24
Нестатические методы класса: пример

class Book
{
/* … */
// конструктор по умолчанию
Book();
// конструктор копирования
Book(const Book &other);
// деструктор
~Book();
/* … */
void printInfo();
string getISBN(char *format = NULL);
};

25
Встроенные методы класса
Функция-член, определенная внутри класса, по умолчанию
является встроенной, то есть подставляемой (на уровне
объектного кода) в точку своего вызова.
Чтобы интерпретироваться как встроенная, функция-член,
определенная вне класса, в теле класса должна явно
сопровождаться спецификатором inline.
Конструктор класса может быть объявлен как встроенный.
Деструктор класса также может быть встроенным.

26
Встроенные методы класса: пример

class Account
{
/* … */
double getAmount() { return _amount; }
inline string getCurrCode()
{ return _currCode; }
inline string getAccInfo(char *format);
};
inline string
Account::getAccInfo(char *format)
{ /* … */ }

27
Константные методы класса
Методы класса могут модифицировать атрибуты
соответствующего объекта, а могут не делать этого. «Безопасные»
с точки зрения работы с константными объектами методы могут
помечаться программистом как константные.
Константный метод не может модифицировать атрибуты класса (за
исключением изменчивых). Применительно к константному объекту
могут быть вызваны только константные методы. Константные
методы могут перегружаться неконстантными методами с
идентичной сигнатурой и типом возвращаемого значения.
Примечание: Применение константных методов с неконстантными
объектами обеспечивает дополнительный уровень безопасности
кода при разработке.
28
Константные методы класса: пример

class Book
{
/* … */
void printInfo() const;
// перегруженные методы
string getChapTitle(int number);
string getChapTitle(int number) const;
};

29
Статические методы класса
Методы класса, обращающиеся только к статическим членам
данных, могут объявляться как статические.
Статическим методам класса не передается указатель this. Они не
могут быть константными или неустойчивыми.
Для вызова статического метода класса может использоваться
операция доступа с леводопустимым выражением или операция
разрешения области видимости с именем класса в качестве
левого операнда. Например:
class BinaryTree
{
/* … */
public:
static char *getFmt() { /* … */ }
private:
static char *_format;
};
30
Неустойчивые методы класса
Методы класса могут объявляться как неустойчивые.
Неустойчивые методы класса являются единственной категорией
методов, которые (наряду с конструкторами и деструкторами)
могут вызываться применительно к неустойчивым объектам
класса (объектам, значение которых изменяется способом, не
обнаруживаемым компилятором).
Например:
class Timer
{
/* … */
void getCurTime() volatile;
/* … */
};
31
Указатели на атрибуты класса
Наряду с «обычными» указателями на данные и глобальные
функции выделяют указатели на нестатические методы и
атрибуты классов.
Примечание: Указатели на статические члены класса оформляются
и используются так же, как указатели на объекты, не являющиеся
членами класса.
Полный тип указателя на атрибут класса содержит имя класса и
тип его атрибута. Например:
class Screen {
public: short _height; /* … */
};
short Screen::*psh = &Screen::_height;
32
Указатели на методы класса (1 / 2)
Полный тип указателя на метод класса содержит имя класса,
список типов параметров (сигнатуру) метода и тип возвращаемого
значения.
Например:
class Screen {
public: int height() { return _height; }
int width() { return _width; }
/* … */
};
int (Screen::*pmeth1)() = NULL;
int (Screen::*pmeth2)() = &Screen::width;
// прочтите следующее определение
typedef Screen& (Screen::*Action)();
33
Указатели на методы класса (2 / 2)
Адреса методов нельзя присваивать указателям на глобальные
функции, даже если их сигнатуры и типы возвращаемых значений
полностью совпадают. Причина: методы класса находятся в
области видимости класса-владельца.
Адреса методов можно использовать для объявления формальных
параметров функций, типов возвращаемого значения и задания
значений параметров функций по умолчанию.
Для доступа к атрибутам и методам класса по указателям
предназначены операции .* и ->*. Например:
Screen *tmpScreen = new Screen();
short Screen::*psh = &Screen::_height;
tmpScreen->*psh = 80;
34
Дружественные классы и функции
Реализованный в объектной модели C++ механизм
дружественных отношений позволяет классу разрешать доступ
к своим неоткрытым (закрытым и защищенным) членам.
Дружественные объекты не являются членами класса, поэтому на
них не распространяется действие спецификаторов доступа.
Отношения дружественности могут устанавливаться:
 между классом и функцией из пространства имен;
 между классом и методом другого класса;
 между двумя классами.

Синтаксис отношений дружественности прекрасно иллюстрирует
перегрузка операций >> и << для организации потокового
консольного и файлового ввода-вывода.

35
Потоковый ввод-вывод (1 / 2)
Консольный и файловый потоковый ввод-вывод экземпляра
класса организуется путем перегрузки операций >> и <<, которая
производится следующим образом:
#include <iostream>
class Account
{
friend istream
operator
friend ostream
operator
/* … */
};

&
>>(istream &, Account &);
&
<<(ostream &, Account &);

36
Потоковый ввод-вывод (2 / 2)
Реализация каждого из дружественных методов тривиальна:
#include <iostream>
ostream &operator <<
(ostream &ostr, Account &acc)
{
ostr << "Name: " << acc._name << "; "
<< "Acc. No.: " << acc._number << "; "
/* << … */ << endl;
return ostr;
};

Для обеспечения файлового ввода-вывода используются потоки
классов ifstream (входной поток) и ofstream (выходной поток).
Дополнительная перегрузка операций >> и << не требуется.
37
Классы-объединения
Объединение в C++ — специальная категория класса, в
котором члены данных физически располагаются, начиная с
одного машинного адреса.
Размер класса-объединения
определяется размерами его
атрибутов и в целом равен
максимальному среди них.
В любой момент времени
значение может быть
присвоено только одному
атрибуту.
38
Классы-объединения: пример

union DataChunk
{
int
intVal;
short shortVal;
char* ptrVal;
double dblVal;
};
DataChunk dc;
DataChunk *pdc = &dc;
dc.intVal = 0xFFAA;
pdc->shortVal = 077;

39
Безымянные объединения

// имя типа объединения может быть опущено
class IOPort
{
/* … */
union
{
int
intVal;
short
shortVal;
char*
ptrVal;
double dblVal;
} _value;
} port;
port._value.intVal = 0xABCD;

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

41
Анонимные объединения: пример

class IOPort
{
/* … */
union {
int
intVal;
short
shortVal;
char*
ptrVal;
double dblVal;
};
} port;
port.ptrVal = NULL;

42
Битовые поля в определении классов
Для хранения заданного числа двоичных разрядов может быть
определен член класса, называемый битовым полем. Его тип
должен быть знаковым или беззнаковым целым.
Определенные друг за другом битовые поля по возможности
«упаковываются» компилятором. Например:
class IOPort
{
unsigned int _ioMode : 2;
unsigned int _enabled : 1;
/* … */
};

К битовому полю запрещено применять оператор взятия адреса.
Битовые поля не могут быть статическими членами класса.
43
Класс как область видимости
Класс — наряду с блоком, функцией и пространством имен —
является конструкцией C++, которая вводит в состав программы
одноименную область видимости. (Строго говоря, область
видимости вводит определение класса, а именно его тело.)
• Все члены класса видны в нем самом с момента своего объявления. Порядок
объявления членов класса важен: нельзя ссылаться на члены, которые
предстоит объявить позднее. Исключение составляет разрешение имен в
определениях встроенных методов, а также имен (статических членов),
используемых как аргументы по умолчанию.

В области видимости класса находится не только его тело, но и
внешние определения его членов: методов и статических
атрибутов.
44
Вложенные классы
Класс, объявленный внутри другого класса, называется
вложенным (в объемлющий класс). При этом:
• определение вложенного класса может находиться в любой секции
объемлющего, а его имя известно в области видимости объемлющего
класса, но нигде более;
• объемлющий класс имеет право доступа только к открытым членам
вложенного, и обратно;

• как правило, вложенный класс объявляют закрытым в объемлющем, а все
члены вложенного класса объявляют открытыми;
• невстроенные методы вложенных классов определяются вне самого
внешнего из объемлющих классов;
• вложенный класс может быть объявлен в теле объемлющего, но не
определен в нем (принцип сокрытия реализации).
45
Конструкторы и деструкторы (1 / 2)
Конструктор — метод класса, автоматически применяемый к
каждому экземпляру (объекту) класса перед первым
использованием (в случае динамического выделения памяти —
после успешного выполнения операции new).
Освобождение ресурсов, захваченных в конструкторе класса либо
на протяжении времени жизни соответствующего экземпляра,
осуществляет деструктор.
В связи с принятым по умолчанию почленным порядком
инициализации и копирования объектов класса в большинстве
случаев возникает необходимость в реализации, — наряду с
конструктором по умолчанию, — конструктора копирования и
перегруженной операции-функции присваивания operator=.
46
Конструкторы и деструкторы (2 / 2)
Выполнение любого конструктора состоит из двух фаз:
 фаза явной (неявной) инициализации (обработка списка
инициализации);
 фаза вычислений (исполнение тела конструктора).

Конструктор не может определяться со спецификаторами
const и volatile. Константность и неустойчивость объекта
устанавливается по завершении работы конструктора и
снимается перед вызовом деструктора.

47
Практикум №3

Постановка задачи
 Сформировать команду (выполнено!).
 Выбрать стандартную или предложить собственную тему
проекта (см. блог дисциплины).
 Построить концептуальную UML-модель предметной области
проекта и детализировать состав основных классов.
 Цель — спроектировать полиморфную иерархию из трех или
более классов с множественным наследованием, семантика и
функциональная нагрузка которых определяются темой
проекта.
48
Спасибо за внимание
Алексей Петров

More Related Content

PDF
C++ осень 2013 лекция 7
PDF
C++ осень 2013 лекция 8
PDF
C++ осень 2013 лекция 4
PDF
C++ осень 2013 лекция 9
PDF
C++ осень 2013 лекция 2
PDF
C++ весна 2014 лекция 5
PDF
C++ весна 2014 лекция 2
PDF
C++ осень 2013 лекция 6
C++ осень 2013 лекция 7
C++ осень 2013 лекция 8
C++ осень 2013 лекция 4
C++ осень 2013 лекция 9
C++ осень 2013 лекция 2
C++ весна 2014 лекция 5
C++ весна 2014 лекция 2
C++ осень 2013 лекция 6

What's hot (20)

PDF
C++ осень 2013 лекция 1
PDF
C++ осень 2012 лекция 6
PDF
C# Desktop. Занятие 01.
PDF
C# Desktop. Занятие 02.
PDF
C++ Базовый. Занятие 04.
PDF
C# Desktop. Занятие 04.
PDF
C++ Базовый. Занятие 11.
PDF
C++ Базовый. Занятие 02.
PPTX
Лекция 6_принципы ООП : инкапсуляция, наследование
PPTX
Классы и объекты в Java
PPTX
Наследование и полиморфизм
PDF
PPTX
Классы и объекты в Java
PDF
Глава 2: Среда разработки NetBeans
PDF
C++ Базовый. Занятие 03.
PDF
C++ осень 2013 лекция 5
PPTX
Java Core. Lecture# 3. Part# 1. Abstract classes.
PPTX
Java Core. Lecture# 2. Classes & objects.
PDF
C++ Базовый. Занятие 15.
C++ осень 2013 лекция 1
C++ осень 2012 лекция 6
C# Desktop. Занятие 01.
C# Desktop. Занятие 02.
C++ Базовый. Занятие 04.
C# Desktop. Занятие 04.
C++ Базовый. Занятие 11.
C++ Базовый. Занятие 02.
Лекция 6_принципы ООП : инкапсуляция, наследование
Классы и объекты в Java
Наследование и полиморфизм
Классы и объекты в Java
Глава 2: Среда разработки NetBeans
C++ Базовый. Занятие 03.
C++ осень 2013 лекция 5
Java Core. Lecture# 3. Part# 1. Abstract classes.
Java Core. Lecture# 2. Classes & objects.
C++ Базовый. Занятие 15.
Ad

Viewers also liked (20)

PDF
ПВТ - осень 2014 - Лекция 7. Многопоточное программирование без блокировок. М...
PDF
ПВТ - осень 2014 - Лекция 5 - Многопоточное программирование в языке С++. Р...
PDF
ПВТ - осень 2014 - лекция 1а - Описание курса
PDF
ПВТ - осень 2014 - Лекция 6 - Атомарные операции. Внеочередное выполнение инс...
PDF
ПВТ - осень 2014 - Лекция 4 - Стандарт POSIX Threads. Реентерабельность. Сигн...
PPT
типы данных в с++
PDF
Дополненная Реальность в Облаке
PDF
Кулагин И.И., Пазников А.А., Курносов М.Г. Оптимизация информационных обменов...
PPTX
PDF
Lec4 хereglegchiinpunkts
PDF
ПВТ - весна 2015 - Лекция 7. Модель памяти С++. Внеочередное выполнение инстр...
PDF
Лекция 5. Метод конечных разностей (параллельные алгоритмы в стандарте MPI)
PDF
Вебинар: Основы распараллеливания С++ программ при помощи OpenMP
PDF
Automated Memory Management for C++
PPTX
АиСД осень 2012 лекция 12
PDF
Страуструп - Язык программирования C++
PDF
Лекция 4. Производные типы данных в стандарте MPI
PDF
ПВТ - весна 2015 - Лекция 4. Шаблоны многопоточного программирования
PDF
Лекция 3. Виртуальные топологии в MPI. Параллельные алгоритмы в стандарте MPI...
PDF
Лекция 1. Основные понятия стандарта MPI. Дифференцированные обмены
ПВТ - осень 2014 - Лекция 7. Многопоточное программирование без блокировок. М...
ПВТ - осень 2014 - Лекция 5 - Многопоточное программирование в языке С++. Р...
ПВТ - осень 2014 - лекция 1а - Описание курса
ПВТ - осень 2014 - Лекция 6 - Атомарные операции. Внеочередное выполнение инс...
ПВТ - осень 2014 - Лекция 4 - Стандарт POSIX Threads. Реентерабельность. Сигн...
типы данных в с++
Дополненная Реальность в Облаке
Кулагин И.И., Пазников А.А., Курносов М.Г. Оптимизация информационных обменов...
Lec4 хereglegchiinpunkts
ПВТ - весна 2015 - Лекция 7. Модель памяти С++. Внеочередное выполнение инстр...
Лекция 5. Метод конечных разностей (параллельные алгоритмы в стандарте MPI)
Вебинар: Основы распараллеливания С++ программ при помощи OpenMP
Automated Memory Management for C++
АиСД осень 2012 лекция 12
Страуструп - Язык программирования C++
Лекция 4. Производные типы данных в стандарте MPI
ПВТ - весна 2015 - Лекция 4. Шаблоны многопоточного программирования
Лекция 3. Виртуальные топологии в MPI. Параллельные алгоритмы в стандарте MPI...
Лекция 1. Основные понятия стандарта MPI. Дифференцированные обмены
Ad

Similar to C++ осень 2013 лекция 3 (20)

PDF
C++ осень 2012 лекция 1
PDF
C++ Базовый. Занятие 08.
PDF
C++ осень 2012 лекция 2
PPTX
принципы ооп и программирование классов в C#
PDF
C++ Базовый. Занятие 09.
PDF
Объектно-Ориентированное Программирование на C++, Лекции 3 и 4
PDF
C++ for real_programmers
PDF
книга с++
PDF
C++ осень 2012 лекция 9
PDF
C++ осень 2012 лекция 3
PDF
Дмитрий Прокопцев — R-ссылки в С++11
PPTX
особенности программирования на с++
PPT
PDF
углубленное программирование на C++. лекция no.5 [4.0]
PPT
Step 3.1
PPTX
принципы объектного подхода
PPTX
разработка бизнес приложений (6)
PDF
Лекция 1. Основы объектно-ориентированного программирования
PDF
Дмитрий Прокопцев "Memory-mapped storage: ещё один подход к сериализации данных"
C++ осень 2012 лекция 1
C++ Базовый. Занятие 08.
C++ осень 2012 лекция 2
принципы ооп и программирование классов в C#
C++ Базовый. Занятие 09.
Объектно-Ориентированное Программирование на C++, Лекции 3 и 4
C++ for real_programmers
книга с++
C++ осень 2012 лекция 9
C++ осень 2012 лекция 3
Дмитрий Прокопцев — R-ссылки в С++11
особенности программирования на с++
углубленное программирование на C++. лекция no.5 [4.0]
Step 3.1
принципы объектного подхода
разработка бизнес приложений (6)
Лекция 1. Основы объектно-ориентированного программирования
Дмитрий Прокопцев "Memory-mapped storage: ещё один подход к сериализации данных"

More from Technopark (20)

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

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

  • 2. Лекция №3. Специальные вопросы инкапсуляции 1. Определение и состав класса. Работа с членами класса и указателями на них. 2. Дружественные классы и функции. 3. Вложенные типы. 4. Инициализация, копирование, преобразование и уничтожение объектов. 5. Инкапсуляция и вопросы производительности. 6. Постановка задач к практикуму №3. 2
  • 3. Инкапсуляция — базовый принцип ООП Инкапсуляция, или сокрытие реализации, является фундаментом объектного подхода к разработке ПО. • Следуя данному подходу, программист рассматривает задачу в терминах предметной области, а создаваемый им продукт видит как совокупность абстрактных сущностей — классов (в свою очередь формально являющихся пользовательскими типами). • Инкапсуляция предотвращает прямой доступ к внутреннему представлению класса из других классов и функций программы. • Без нее теряют смысл остальные основополагающие принципы объектноориентированного программирования (ООП): наследование и полиморфизм. Сущность инкапсуляции можно отразить формулой: Открытый интерфейс + скрытая реализация 3
  • 4. Класс: в узком или широком смысле? Принцип инкапсуляции распространяется не только на классы (class), но и на структуры (struct), а также объединения (union). Это связано с расширительным толкованием понятия «класс» в языке C++, трактуемом как в узком, так и широком смысле: • класс в узком смысле — одноименный составной пользовательский тип данных, являющийся контейнером для данных и алгоритмов их обработки. Вводится в текст программы определением типа со спецификатором class; • класс в широком смысле — любой составной пользовательский тип данных, агрегирующий данные и алгоритмы их обработки. Вводится в текст программы определением типа с одним из спецификаторов struct, union или class. Каждое определение класса вводит новый тип данных. Тело класса определяет полный перечень его членов, который не может быть расширен после закрытия тела. 4
  • 5. Определение класса: пример // пустой класс class Document { }; // непустой класс class Book { public: Book(); private: string _author, _title; }; 5
  • 6. Описание класса Описание класса вида <спецификатор класса> <имя класса>; вводит в программу имя класса и указывает его природу, не определяя состав атрибутов, методов и иных частей класса. В случае если класс описан, но не определен, допускается:  определять ссылки и указатели на объект класса;  определять член другого класса как ссылку или указатель на данный класс. В случае если класс описан, но не определен, запрещается:     определять объект класса; определять член другого класса как принадлежащий данному классу; разыменовывать указатели на объект класса; использовать ссылки и указатели для доступа к членам класса. 6
  • 7. Описание класса: пример // описание класса class Account; // допустимо // определения объектов: Account *pAcc = NULL; // допустимо void foo(const Account *pA); // допустимо class Account acc; // недопустимо 7
  • 8. Объект класса Выделение памяти под объект (экземпляр) класса происходит при определении такого объекта, ссылки на объект или указателя на него. Объект класса: • имеет размер, достаточный для размещения в нем всех (нестатических) атрибутов, собственную копию каждого из которых имеет каждый индивидуальный объект; • характеризуется областью видимости и обладает временем жизни. Объекты одного класса могут присваиваться друг другу. В отсутствие в определении класса конструктора копирования копирование объектов эквивалентно копированию атрибутов по правилам копирования значений их типов. Будучи параметром или возвращаемым значением функции, объект класса передается через стек по значению. 8
  • 9. Объект класса: пример // определение класса (и объекта — допустимо) class Account { /* … */ }; class Deposit { /* … */ } deposit; // определения объектов: допустимо class Account acc; Account *pAcc = new Account(100); Account &rAcc = acc; class Account *&prAcc = pAcc; // определения объектов: недопустимо Account &rAcc2 = &acc; 9
  • 10. Константный объект класса (1 / 2) Объект класса (как и объект базового типа) может быть объявлен константным. Константный объект не допускает изменения значения его атрибутов на протяжении всего времени жизни объекта, за исключением:  времени работы конструктора (объект создается);  времени работы деструктора (объект уничтожается). 10
  • 11. Константный объект класса (2 / 2) Неизменность членов-данных, являющихся указателями, распространяется только на их значение (адрес) и не распространяется на содержимое областей памяти, которые они адресуют. Примечание: Модификация адресуемых таким образом областей памяти демонстрирует «плохой стиль» программирования Например: const Document myDocument; 11
  • 12. Состав класса: атрибуты За содержательную сторону класса на языке C++ отвечают входящие в него атрибуты (члены данных):  статические (со спецификатором static):  в том числе константные (со спецификатором const);  неустойчивые (со спецификатором volatile);  изменчивые (со спецификатором mutable);  прочие (без формальных спецификаторов). 12
  • 13. Состав класса: методы За алгоритмическую сторону класса на языке C++ отвечают входящие в него методы (функции-члены), в том числе специальные (конструкторы и деструкторы):      встроенные (со спецификатором inline); константные (со спецификатором const); статические (со спецификатором static); неустойчивые (со спецификатором volatile); прочие (без формальных спецификаторов). 13
  • 14. Состав класса: прочие элементы В состав класса на языке C++, помимо атрибутов и методов, могут входить следующие прочие элементы:  описания дружественных объектов:  прототипы дружественных функций;  описания дружественных классов;  определения типов;  битовые поля;  вложенные классы. 14
  • 15. Нестатические члены данных За содержательную сторону класса ответственны его атрибуты. Чаще всего каждый экземпляр (объект) класса имеет свой набор нестатических атрибутов. Нестатические члены данных сопоставляются с конкретным экземпляром класса и тиражируются. Время жизни такого члена данных равно времени жизни объекта. Нестатические члены данных нельзя инициализировать в теле класса. Для обращения к нестатическим членам данных служат операции доступа (. или ->), левым операндом которых выступает леводопустимое выражение: идентификатор объекта, ссылка или указатель на объект (допустимый вариант — this, см. далее). 15
  • 16. Нестатические члены данных: пример class Book { /* … */ int _pages; string _title; vector<string> _chapTitles; /* … */ } book; Book *pBook = &book; /* … */ book._pages = 100; // эквивалентно: pBook->_pages = 100; // эквивалентно: (*pBook)._pages = 100; 16
  • 17. Статические члены данных (1 / 2) Статический член данных класса — это глобальный объект, совместно используемый всеми объектами своего класса. Статические объекты не тиражируются и существуют даже при отсутствии экземпляров, поскольку связаны не с переменной (объектом), а типом (классом). Преимущества статических членов данных перед глобальными объектами состоят в том, что:  статические члены находятся в области видимости класса, а не в глобальном пространстве имен;  на статические члены распространяется действие спецификаторов доступа. 17
  • 18. Статические члены данных (2 / 2) Обычно статический член инициализируется вне определения класса. Определение статического члена данных в программе может быть лишь одно. Для обращения к статическому члену класса могут использоваться: • операция доступа с леводопустимым выражением; • операция разрешения области видимости с именем класса в качестве левого операнда. Примечание: В качестве исключения константный статический член целого типа может быть инициализирован в теле класса. В этом случае он трактуется как именованная константа. Статический член данных может иметь тот же тип класса, членом которого он является, а также быть аргументом по умолчанию для его метода. 18
  • 19. Статические члены данных: пример class BinaryTree { /* … */ static char static const short static const char }; delimiter; base = 10; *_format; char BinaryTree::delimiter = ','; const char *BinaryTree::_format = "(%d) %d,_"; BinaryTree tree; // ... tree.delimiter = ' '; BinaryTree::delimiter = ';'; 19
  • 20. Неустойчивые объекты (1 / 2) Неустойчивые, или асинхронно изменяемые (volatile), объекты могут изменяться незаметно для компилятора. Пример: Переменная, обновляемая значением системных часов или значением, полученным через системный порт. Целью определения объекта как неустойчивого является информирование компилятора о том, что тот не может определить, каким образом может изменяться значение данного объекта. Спецификатор volatile сообщает компилятору о том, что при работе с данным объектом не следует выполнять оптимизацию кода. 20
  • 21. Неустойчивые объекты (2 / 2) Допустимы неустойчивые объекты скалярных и составных типов, указатели на неустойчивые объекты, неустойчивые массивы:  в неустойчивом массиве неустойчивым считается каждый элемент;  в неустойчивом экземпляре (объекте) класса неустойчивым считается каждый член данных. Объекты классов неустойчивы целиком. Например: volatile unsigned long timer;// неустойчивый скаляр volatile short ports[size]; // неустойчивый массив // указатель на неустойчивый объект класса volatile Timer *tmr; Для преобразования неустойчивого типа в устойчивый используется const_cast. 21
  • 22. Изменчивые члены данных Атрибуты класса, допускающие модификацию при любом использовании объекта, должны определяться как изменчивые. Изменчивые атрибуты не являются константными, даже будучи членами константного объекта, что позволяет модифицировать их значения, в том числе константными методами. Например: class Book { /* ... */ mutable int _currentPage; /* ... */ void locate(const int &value) const { /* ... */ _currentPage = value; /* ... */ } }; 22
  • 23. Указатель this Указатель this — неявно определяемый константный указатель на объект класса, через который происходит вызов соответствующего нестатического метода. Для неконстантных методов класса T имеет тип T *const, для константных — имеет тип const T *const, для неустойчивых — volatile T *const. Указатель this допускает разыменование (*this). Применение this внутри методов допустимо, но чаще всего излишне. Исключение составляют две ситуации:  сравнение адресов объектов: if (this != someObj) /* … */  оператор return: return *this; 23
  • 24. Нестатические методы класса За поведение реализованной в виде класса абстракции отвечают функции-члены (методы). В отличие от атрибутов, методы класса существуют в единственном экземпляре, причем даже тогда, когда ни один объект класса не существует. Подавляющее большинство методов класса оперирует нестатическими атрибутами и в этом смысле может условно именоваться нестатическими методами. Для методов произвольного класса справедливо следующее:  методы класса имеют доступ ко всем атрибутам класса;  методы класса могут перегружать другие методы того же класса;  нестатические методы класса получают в свое распоряжение указатель this. 24
  • 25. Нестатические методы класса: пример class Book { /* … */ // конструктор по умолчанию Book(); // конструктор копирования Book(const Book &other); // деструктор ~Book(); /* … */ void printInfo(); string getISBN(char *format = NULL); }; 25
  • 26. Встроенные методы класса Функция-член, определенная внутри класса, по умолчанию является встроенной, то есть подставляемой (на уровне объектного кода) в точку своего вызова. Чтобы интерпретироваться как встроенная, функция-член, определенная вне класса, в теле класса должна явно сопровождаться спецификатором inline. Конструктор класса может быть объявлен как встроенный. Деструктор класса также может быть встроенным. 26
  • 27. Встроенные методы класса: пример class Account { /* … */ double getAmount() { return _amount; } inline string getCurrCode() { return _currCode; } inline string getAccInfo(char *format); }; inline string Account::getAccInfo(char *format) { /* … */ } 27
  • 28. Константные методы класса Методы класса могут модифицировать атрибуты соответствующего объекта, а могут не делать этого. «Безопасные» с точки зрения работы с константными объектами методы могут помечаться программистом как константные. Константный метод не может модифицировать атрибуты класса (за исключением изменчивых). Применительно к константному объекту могут быть вызваны только константные методы. Константные методы могут перегружаться неконстантными методами с идентичной сигнатурой и типом возвращаемого значения. Примечание: Применение константных методов с неконстантными объектами обеспечивает дополнительный уровень безопасности кода при разработке. 28
  • 29. Константные методы класса: пример class Book { /* … */ void printInfo() const; // перегруженные методы string getChapTitle(int number); string getChapTitle(int number) const; }; 29
  • 30. Статические методы класса Методы класса, обращающиеся только к статическим членам данных, могут объявляться как статические. Статическим методам класса не передается указатель this. Они не могут быть константными или неустойчивыми. Для вызова статического метода класса может использоваться операция доступа с леводопустимым выражением или операция разрешения области видимости с именем класса в качестве левого операнда. Например: class BinaryTree { /* … */ public: static char *getFmt() { /* … */ } private: static char *_format; }; 30
  • 31. Неустойчивые методы класса Методы класса могут объявляться как неустойчивые. Неустойчивые методы класса являются единственной категорией методов, которые (наряду с конструкторами и деструкторами) могут вызываться применительно к неустойчивым объектам класса (объектам, значение которых изменяется способом, не обнаруживаемым компилятором). Например: class Timer { /* … */ void getCurTime() volatile; /* … */ }; 31
  • 32. Указатели на атрибуты класса Наряду с «обычными» указателями на данные и глобальные функции выделяют указатели на нестатические методы и атрибуты классов. Примечание: Указатели на статические члены класса оформляются и используются так же, как указатели на объекты, не являющиеся членами класса. Полный тип указателя на атрибут класса содержит имя класса и тип его атрибута. Например: class Screen { public: short _height; /* … */ }; short Screen::*psh = &Screen::_height; 32
  • 33. Указатели на методы класса (1 / 2) Полный тип указателя на метод класса содержит имя класса, список типов параметров (сигнатуру) метода и тип возвращаемого значения. Например: class Screen { public: int height() { return _height; } int width() { return _width; } /* … */ }; int (Screen::*pmeth1)() = NULL; int (Screen::*pmeth2)() = &Screen::width; // прочтите следующее определение typedef Screen& (Screen::*Action)(); 33
  • 34. Указатели на методы класса (2 / 2) Адреса методов нельзя присваивать указателям на глобальные функции, даже если их сигнатуры и типы возвращаемых значений полностью совпадают. Причина: методы класса находятся в области видимости класса-владельца. Адреса методов можно использовать для объявления формальных параметров функций, типов возвращаемого значения и задания значений параметров функций по умолчанию. Для доступа к атрибутам и методам класса по указателям предназначены операции .* и ->*. Например: Screen *tmpScreen = new Screen(); short Screen::*psh = &Screen::_height; tmpScreen->*psh = 80; 34
  • 35. Дружественные классы и функции Реализованный в объектной модели C++ механизм дружественных отношений позволяет классу разрешать доступ к своим неоткрытым (закрытым и защищенным) членам. Дружественные объекты не являются членами класса, поэтому на них не распространяется действие спецификаторов доступа. Отношения дружественности могут устанавливаться:  между классом и функцией из пространства имен;  между классом и методом другого класса;  между двумя классами. Синтаксис отношений дружественности прекрасно иллюстрирует перегрузка операций >> и << для организации потокового консольного и файлового ввода-вывода. 35
  • 36. Потоковый ввод-вывод (1 / 2) Консольный и файловый потоковый ввод-вывод экземпляра класса организуется путем перегрузки операций >> и <<, которая производится следующим образом: #include <iostream> class Account { friend istream operator friend ostream operator /* … */ }; & >>(istream &, Account &); & <<(ostream &, Account &); 36
  • 37. Потоковый ввод-вывод (2 / 2) Реализация каждого из дружественных методов тривиальна: #include <iostream> ostream &operator << (ostream &ostr, Account &acc) { ostr << "Name: " << acc._name << "; " << "Acc. No.: " << acc._number << "; " /* << … */ << endl; return ostr; }; Для обеспечения файлового ввода-вывода используются потоки классов ifstream (входной поток) и ofstream (выходной поток). Дополнительная перегрузка операций >> и << не требуется. 37
  • 38. Классы-объединения Объединение в C++ — специальная категория класса, в котором члены данных физически располагаются, начиная с одного машинного адреса. Размер класса-объединения определяется размерами его атрибутов и в целом равен максимальному среди них. В любой момент времени значение может быть присвоено только одному атрибуту. 38
  • 39. Классы-объединения: пример union DataChunk { int intVal; short shortVal; char* ptrVal; double dblVal; }; DataChunk dc; DataChunk *pdc = &dc; dc.intVal = 0xFFAA; pdc->shortVal = 077; 39
  • 40. Безымянные объединения // имя типа объединения может быть опущено class IOPort { /* … */ union { int intVal; short shortVal; char* ptrVal; double dblVal; } _value; } port; port._value.intVal = 0xABCD; 40
  • 41. Анонимные объединения Объединение без имени, за которым не следует определение объекта, называется анонимным. К его членам можно обращаться непосредственно из той области видимости, в которой оно определено. Анонимные объединения позволяют устранить один уровень доступа, у них не может быть закрытых и защищенных членов, а также каких бы то ни было методов. 41
  • 42. Анонимные объединения: пример class IOPort { /* … */ union { int intVal; short shortVal; char* ptrVal; double dblVal; }; } port; port.ptrVal = NULL; 42
  • 43. Битовые поля в определении классов Для хранения заданного числа двоичных разрядов может быть определен член класса, называемый битовым полем. Его тип должен быть знаковым или беззнаковым целым. Определенные друг за другом битовые поля по возможности «упаковываются» компилятором. Например: class IOPort { unsigned int _ioMode : 2; unsigned int _enabled : 1; /* … */ }; К битовому полю запрещено применять оператор взятия адреса. Битовые поля не могут быть статическими членами класса. 43
  • 44. Класс как область видимости Класс — наряду с блоком, функцией и пространством имен — является конструкцией C++, которая вводит в состав программы одноименную область видимости. (Строго говоря, область видимости вводит определение класса, а именно его тело.) • Все члены класса видны в нем самом с момента своего объявления. Порядок объявления членов класса важен: нельзя ссылаться на члены, которые предстоит объявить позднее. Исключение составляет разрешение имен в определениях встроенных методов, а также имен (статических членов), используемых как аргументы по умолчанию. В области видимости класса находится не только его тело, но и внешние определения его членов: методов и статических атрибутов. 44
  • 45. Вложенные классы Класс, объявленный внутри другого класса, называется вложенным (в объемлющий класс). При этом: • определение вложенного класса может находиться в любой секции объемлющего, а его имя известно в области видимости объемлющего класса, но нигде более; • объемлющий класс имеет право доступа только к открытым членам вложенного, и обратно; • как правило, вложенный класс объявляют закрытым в объемлющем, а все члены вложенного класса объявляют открытыми; • невстроенные методы вложенных классов определяются вне самого внешнего из объемлющих классов; • вложенный класс может быть объявлен в теле объемлющего, но не определен в нем (принцип сокрытия реализации). 45
  • 46. Конструкторы и деструкторы (1 / 2) Конструктор — метод класса, автоматически применяемый к каждому экземпляру (объекту) класса перед первым использованием (в случае динамического выделения памяти — после успешного выполнения операции new). Освобождение ресурсов, захваченных в конструкторе класса либо на протяжении времени жизни соответствующего экземпляра, осуществляет деструктор. В связи с принятым по умолчанию почленным порядком инициализации и копирования объектов класса в большинстве случаев возникает необходимость в реализации, — наряду с конструктором по умолчанию, — конструктора копирования и перегруженной операции-функции присваивания operator=. 46
  • 47. Конструкторы и деструкторы (2 / 2) Выполнение любого конструктора состоит из двух фаз:  фаза явной (неявной) инициализации (обработка списка инициализации);  фаза вычислений (исполнение тела конструктора). Конструктор не может определяться со спецификаторами const и volatile. Константность и неустойчивость объекта устанавливается по завершении работы конструктора и снимается перед вызовом деструктора. 47
  • 48. Практикум №3 Постановка задачи  Сформировать команду (выполнено!).  Выбрать стандартную или предложить собственную тему проекта (см. блог дисциплины).  Построить концептуальную UML-модель предметной области проекта и детализировать состав основных классов.  Цель — спроектировать полиморфную иерархию из трех или более классов с множественным наследованием, семантика и функциональная нагрузка которых определяются темой проекта. 48