- •Определение класса
- •Пример (точка)
- •Оператор вывода (пример)
- •Параметр шаблона по умолчанию (пример)
- •Где перехватывать исключения?
- •Гарантии безопасности исключений
- •Базовые операции
- •Виртуальная функция
- •Использование virtual
- •Массив, как диапазон
- •Контейнер
- •Свойства элемента контейнера
- •Заголовочные файлы
- •Доступ к элементам list
- •Размеры list
- •Доступ к элементам map
- •Очередь с приоритетом
- •Дэк (двусвязная очередь)
- •Матрица (в математике)
- •Атд “матрица”
- •Дерево (доп. Определения)
- •Узел дерева (доп. Определения)
- •“Родственные отношения”
- •“Родственные отношения” (иллюстрация)
- •Баланс в дереве (иллюстрация)
- •Std::less (пример функтора)
- •Std::find_if (пример алгоритма)
- •Функциональные адаптеры
- •Производящая функция
- •Производящие функции для функциональных адаптеров
Параметр шаблона по умолчанию (пример)
template |
<class |
T> class CStr; //< строки |
template
template |
<class
<class |
T> class СCmp; //< сравнитель символов
T> |
int compare(const CStr<T>& lhs, const CStr<T>& rhs);
template <class T, class C>
int compare(const CStr<T>& |
lhs, const |
CStr<T>& |
rhs); |
или |
|
|
|
template <class T, class C int compare(const CStr<T>& |
= СCmp<T>> lhs, const |
CStr<T>& |
rhs); |
03.03.2012
www.cppNewb.ru 30
Размещение шаблонного кода
определение шаблона д.б. доступно в точке инстанциирования
размещайте весь шаблонный код в
заголовочных файлах
03.03.2012
www.cppNewb.ru 31
Определение функции (пример)
// in .h template<typename T>
T minimum(const T& lhs, const T& rhs);
// in .h template<typename T> T
minimum(const T& lhs, const T& rhs)
{
…
}
03.03.2012
www.cppNewb.ru 32
Определение неподставляемых
методов класса (пример)
// in CArr.h template<typename T> class CArr
{
public:
int size() const;
…
// in CArr.h template<typename T> int
CArr<T>::size() const
{
…
}
};
03.03.2012
www.cppNewb.ru 33
Специализация
версия шаблонного кода для конкретного набора параметров
позволяет реализовывать выбор
оптимальной реализации для заданного набора параметров
03.03.2012
www.cppNewb.ru 34
Параметрический полиморфизм
или
полиморфизм времени компиляции
реализуется с помощью механизма шаблонов
алгоритм выражается один раз и используется многократно со множеством типов
03.03.2012
www.cppNewb.ru 35
Генерируемый код
инстанциирование должно иметь место только для используемого кода
для каждого уникального набора параметров генерируется свой код
возможно “разбухание” программы
03.03.2012
www.cppNewb.ru 36
Сообщения об ошибках в шаблонном коде
требуют внимательного разбора
часто связаны с передачей
недопустимых параметров
03.03.2012
www.cppNewb.ru 37
Стандартная библиотека
STL (Standard Template Library)
шаблонная часть стандартной библиотеки
содержит много полезных и качественно реализованных классов и функций
03.03.2012
www.cppNewb.ru 38
Контейнер (примеры)
массив
фиксированного размера
динамический (std::vector<>)
список (std::list<>)
множество (std::set<>)
строка (std::basic_string<>)
03.03.2012
www.cppNewb.ru 39
Заголовочные файлы
совпадают с именем контейнера
<vector>
<list>
<deque>
<set> - в т.ч. multiset
<map> - в т.ч. multimap
вспомогательные
<utility>
<iterator>
03.03.2012
www.cppNewb.ru 40
vector<>
динамический массив
произвольный доступ
быстрая вставка/удаление в конец
медленная вставка/удаление в начало
изменение числа элементов делает итераторы невалидными
03.03.2012
www.cppNewb.ru 41
Объявление vector
template
<class T,
class Allocator = allocator<T> > class vector
vector<bool> - специализация
03.03.2012
www.cppNewb.ru 42
Доступ к элементам vector
по индексу
замена встроенным массивам
с концов
через итератор
обобщенный вариант
последовательное расположение элементов в памяти
03.03.2012
www.cppNewb.ru 43
Доступ к элементам vector
по индексу
T& at(int i)
с контролем выхода за пределы
T& operator[](int i)
без контроля выхода за пределы
пример:
data.at(iBest) = iCurrent; iNext = data.at(j);
data[iBest] = iCurrent;
03.03.2012
www.cppNewb.ru 44
Доступ к элементам vector
с концов
T& front()
первый элемент
T& back()
последний элемент
03.03.2012
www.cppNewb.ru 45
Доступ к элементам vector (если контейнер const)
const T& operator[](int i) const const T& at(int i) const
const T& front() const
const T& back() const
03.03.2012
www.cppNewb.ru 46
size
Размеры vector
число элементов
empty
проверка на пустоту
capacity
максимальное число элементов (буфер)
max_size
максимальное число элементов (системно)
resize
изменить число элементов
reserve
гарантировать размер буфера (не меньше)
03.03.2012
www.cppNewb.ru 47
Очистка массива
void clear()
удалить все элементы
03.03.2012
www.cppNewb.ru 48
Обмен содержимым для массивов
void
swap(vector<T, Allocator>& vec)
пример:
best.swap(worst);
03.03.2012
www.cppNewb.ru 49
Объектно-ориентированное
программирование
с использованием C++
Полевой Дмитрий Валерьевич к.т.н., доцент КиК
e-mail: oop.misis@gmail.com
АТД
абстрактный тип данных
создание/уничтожение
набор операций
структура данных – реализация АТД
10.03.2010
cppNewb.ru 2
Интерфейс
семантическая и синтаксическая конструкция
спецификация услуг
10.03.2010
cppNewb.ru 3
Класс
реализует одну или несколько абстракций
интерфейс
открытые методы
функции
закон “протекающих абстракций”
10.03.2010
cppNewb.ru 4
создание
АТД “число”
уничтожение
присваивание
сравнение
==, !=, <, <=, >, >=
арифметические операции
-, +=, +, -=, -, *=, *, /=, /
ввод и вывод
10.03.2010
cppNewb.ru 5
Рациональное число (класс)
Rnum(const int num, const int denum) Rnum(const Rnum& num)
~Rnum()
Rnum& operator=(const Rnum& rhs)
bool operator==(const Rnum& rhs) const bool operator<(const Rnum& rhs) const bool operator!=(const Rnum& rhs,
const Rnum& rhs)
…
10.03.2010
cppNewb.ru 6
Рациональное число (класс)
Rnum& operator++() Rnum operator++(int)
Rnum& operator+=(const Rnum& rhs) Rnum operator+(const Rnum& lhs,
const Rnum& rhs)
ostream& operator<<(ostream& ostr, const Rnum& num)
istream& operator>>(istream& istr, Rnum& num)
10.03.2010
cppNewb.ru 7
АТД “динамический массив”
создание
уничтожение
получение доступа к элементу по индексу
получение размера
изменение размера
10.03.2010
cppNewb.ru 8
Динамический массив (класс)
Array(const size_t size) Array(const Array& arr)
~Array()
Array& operator=(const Array& arr) T& at(const size_t index)
const T& at(const size_t index) const size_t size(SArray& arr) const
void resize(const size_t newSize)
10.03.2010
cppNewb.ru 9
Раздельная компиляция
компилятор (compiler)
компиляция независимых компонент
генерация объектного кода
компоновщик (linker)
связывание объектного кода
генерация исполняемого кода
преодоление ограничений компилятора
повторное использование
160.03.20110
cppNewb.ru 10
Этапы сборки программы
препроцессор
компилятор
оптимизатор
компоновщик
10.03.2010
cppNewb.ru 11
Препроцессор
директивы включения
#include
макроопределения
#define, #undef
директивы условной компиляции
#ifndef, #else, #endif
#, ##
10.03.2010
cppNewb.ru 12
Единица компиляции
исходный файл → препроцессор → единица трансляции
компилируется в собственный объектный файл
10.03.2010
cppNewb.ru 13
Использование библиотеки
включить заголовок
использовать
объявления
переменные
функции
скомпоновать библиотеку
10.03.2010
cppNewb.ru 14
Реализация модульности в С++
функция – единица логики исполнения
модуль (.cpp) – единица организации исходного кода
общие объявления выносятся в заголовок
10.03.2010
cppNewb.ru 15
Заголовочные файлы
стандартные
#include <стандартная_библиотека>
пользовательские
#include “включаемая_компонента”
10.03.2010
cppNewb.ru 16
Стандартная библиотека
новые имена для библиотек Си
<stdio.h> → <cstdio>
новые имена для библиотек С++
<iostream.h> → <iostream>
не все библиотеки стандартные
<conio.h>
10.03.2010
cppNewb.ru 17
Порядок поиска
определяется реализацией
может быть причиной “сложных” ошибок
переменные окружения
опции компилятора
текущая папка
10.03.2010
cppNewb.ru 18
Стражи включения
предотвращение повторного определения
пример:
// In file defs.h
#ifndef DEFS_H_20080910
#define DEFS_H_20080910
.
.
.
#endif // DEFS_H_20080910
10.03.2010
cppNewb.ru 19
.h может содержать
директивы включения, макроопределения и директивы условной компиляции
именованные пространства имен
объявления имен типов, функций и данных
определения типов
определения встроенных функций объявления и определения шаблонов
определения констант
перечисления
10.03.2010
cppNewb.ru 20
.h не должен содержать
определения обычных функций
определения данных
определения агрегатов
неименованные пространства имен
10.03.2010
cppNewb.ru 21
Использование заголовочных файлов в проектах
включайте все необходимое
минимизируйте число включений
включайте заголовочные файлы в порядке увеличения общности
локальные
общеупотребительные
стандартные
разделяйте группы заголовков
10.03.2010
cppNewb.ru 22
Бинарный интерфейс компонент
соглашение о параметрах вызова
Си-соглашение
extern “C”
{
// source code
}
10.03.2010
cppNewb.ru 23
l-value
именующее выражение, ссылается на объект (м.б. const)
может стоять в левой части оператора присваивания (если не const)
пример:
int num(1);
num |
= |
5; |
*(p |
+ |
15) |
10.03.2010
cppNewb.ru 24
r-value
не l-value
пример:
5 //< литерал
a + b //< временные объекты new int //< новый объект string(“0”) //< временный объект s.size() //< вызов функции
10.03.2010
cppNewb.ru 25
Пространства имен (namespace)
логически группирует объявления
определяет область видимости
могут быть вложенными
10.03.2010
cppNewb.ru 26
Создание пространства имен
namespace имя_пространства_имен
{
// объявления и определения
}
10.03.2010
cppNewb.ru 27
Создание пространства имен
пример:
namespace misis
{
// Узнать число групп.
int getGroupsCount();
}
10.03.2010
cppNewb.ru 28
Доступ к именам в пространстве
доступ через оператор разрешения области видимости ::
имя_пространства_имен::имя_члена
пример:
std::cout
10.03.2010
cppNewb.ru 29
Глобальное пространство имен
все, что не лежит в собственном пространстве имен
доступ через :: (можно опускать)
10.03.2010
cppNewb.ru 30
using-объявление
вводит локальный синоним
using имя_пространства_имен::имя_члена;
пример:
using std::cout;
cout << "Hello!" << std::endl;
10.03.2010
cppNewb.ru 31
using-директива
вносит все именa из заданного пространства имен в текущее
using namespace имя_пространства_имен;
пример:
using namespace std;
cout << "Hello!" << endl;
10.03.2010
cppNewb.ru 32
Открытость пространства имен
допускается добавление имен в пространство имен в нескольких определениях
10.03.2010
cppNewb.ru 33
Открытость пространства имен
пример:
// В файле parser.h namespace parser
{
bool parse();
}
// В файле lexparser.h namespace parser
{
int getLexCnt();
}
10.03.2010
cppNewb.ru 34
Сокрытие имен
int x(10); // Глобальная переменная.
void f()
{
// Локальная скрывает глобальную.
int x(0);
// Присваивание локальной переменной.
x = 1;
// присваивание глобальной переменной
::x = 5;
}
10.03.2010
cppNewb.ru 35
Знаковость типа
модификаторы
unsigned – неотрицательные значения
signed – знаковые значения
10.03.2010
cppNewb.ru 36
Символьные типы
char – символ (например, ASCII)
wchar_t – символ Unicode
char – от 0 до 255 или от -128 до 127
unsigned char – от 0 до 255
signed char – от -128 до 127
10.03.2010
cppNewb.ru 37
Символьный литерал
заключенный в кавычки символ
пример:
‘a’, ‘\n’, ‘\’
для Unicode
пример:
L‘ab’
10.03.2010
cppNewb.ru 38
Целочисленные типы
int – целое число
модификаторы
short
long
знаковость
10.03.2010
cppNewb.ru 39
Целочисленные литералы
0x – префикс шестнадцатиричного литерала
U – суффикс беззнакового литерала
L – суффикс long-литерала
пример: 125 0x8ABCDEF 3U
3L
10.03.2010
cppNewb.ru 40
Типы с плавающей точкой
float – одинарная точность
double – двойная точность
long double – расширенная точность
10.03.2010
cppNewb.ru 41
Литералы с плавающей точкой
‘.’ – разделитель
F – суффикс float литерала
L – суффикс long double литерала
пример: 12.5 3F 3.0L
1.23E-10
78.3E-1L
10.03.2010
cppNewb.ru 42
Пустой тип (void)
void – в качестве возвращаемого значения, для указания, что функция ничего не возвращает
void* – указатель на объекты
неизвестного типа
10.03.2010
cppNewb.ru 43
Рекомендуемые типы
bool
char
int
double
Выбор типа
unsigned - массив битов
signed – все остальное
требуемая точность
ограничения по использованию памяти
Диапазоны арифметических типов
тип |
минимальный диапазон |
char |
[-128,127] или [0, 255] |
unsigned char |
[0, 255] |
signed char |
[-128, 127] |
int |
[-2^15, 2^15 - 1] |
unsigned int |
[0, 2^16] |
double |
10 значащих цифр |
wchar_t |
как unsigned int |
Размеры арифметических типов
1 == sizeof(char) <= sizeof(short) <= sizeof(int) <= sizeof(long)
sizeof(float) <= sizeof(double) <= sizeof(long double)
sizeof(T) == sizeof(signed T) == sizeof(unsigned T)
Неявные преобразования
повышение
bool -> int
enum -> int или long
обеспечение точности
int + long
int + double -> double
усечение
int n(f);
10.03.2010
cppNewb.ru 48
Округление (примеры)
до целого (с усечением)
пример:
int size(d);
до ближайшего
пример:
int size(d + 0.5);
10.03.2010
cppNewb.ru 49
Явные преобразования
static_cast<Тип>(выражение)
преобразование родственных типов
пример:
int roundVal = static_cast<int>(doubleVal);
10.03.2010
cppNewb.ru 50
Явные преобразования
const_cast<Тип>(выражение)
изменение константности
пример:
char* pBeg = const_cast<char*>(p + n);
10.03.2010
cppNewb.ru 51
Преобразования в стиле С
(Тип)выражение Тип(выражение)
пример:
int roundVal = int(doubleVal + 0.5);
10.03.2010
cppNewb.ru 52
Объектно-ориентированное
программирование
с использованием C++
Полевой Дмитрий Валерьевич к.т.н., доцент КиК
e-mail: oop.misis@gmail.com
Спецификация ПО
точное описание работы программы
корректность – согласованность с некоторой спецификацией
ошибка – нарушение спецификации
17.03.2012
cppNewb.ru 2
Ошибки ПО и ошибки I/O
неправильная реализация алгоритма
некорректный вызов
(из другого фрагмента кода)
некорректный ввод
ошибки пользователя
отказы оборудования (в т.ч. при выводе)
ошибки данных
17.03.2012
cppNewb.ru 3
Некорректный ввод и вывод
НЕ МОЖЕТ СЧИТАТЬСЯ ОШИБКОЙ
реальный мир несовершенен ☺
требуется
диагностика и подсказки пользователю
альтернативные варианты действий
предотвращение потери данных
17.03.2012
cppNewb.ru 4
Как (вы)жить в неидеальном мире
быть “немного параноиком”
тестировать (больше и дешевле)
изолировать подсистемы ввода/вывода
обеспечивать корректные данные для алгоритмической части
предусматривать схемы дублирования и резервирования критической информации
17.03.2012
cppNewb.ru 5
Действия в случае ошибок
игнорировать
сообщить
вывести в консоль
сохранить в протокол
послать сообщение разрабтчикам
и т.д.
17.03.2012
cppNewb.ru 6
Действия в случае ошибок
прекратить исполнение программы
возвратить статус ошибки
возвратить допустимое значение и оставить программу в некорректном состоянии
вызвать функцию для обработки ошибочных ситуаций
17.03.2012
cppNewb.ru 7
пример:
Глобальный статус
int getLastErr(); //< получить статус
void setLastErr(int); //< установить статус
if (ERR_NO == getLastErr())
{
// Основной поток исполнения программы.
}
else
{
// Обработка ошибочной ситуации.
}
17.03.2012
cppNewb.ru 8
Возвращаемое значение
пример:
int doJob();
...
if (ERR_NO == doJob())
{
// Основной поток исполнения программы.
}
else
{
// Обработка ошибочной ситуации.
}
17.03.2012
cppNewb.ru 9
Обработка ошибочных ситуаций
глобальный статус
возвращаемое значение
на ком лежит обработка?
заказчик (клиент)
исполнитель (сервер)
возникновение ошибочной ситуации можно просто игнорировать!
17.03.2012
cppNewb.ru 10
Защитное программирование
программа всегда должна работать
каждая функция защищается как может
кто сломался, тот и виноват
дублирование кода проверок
сложность кода
безответственное программирование
17.03.2012
cppNewb.ru 11
Программирование по контракту
обязанности сторон
клиент: корректные входные данные
поставщик: корректная работа и результат
соблюдение контракта
17.03.2012
cppNewb.ru 12
Контрактные отношения
могут быть между частями программы
программа-программа
не определены с внешней средой
программа-человек программа-внешний мир
17.03.2012
cppNewb.ru 13
Обработка входных данных
модули ввода (фильтры)
гарантия корректности входных данных для обрабатывающих модулей
17.03.2012
cppNewb.ru 14
Контракты в исходном коде
д.б. описаны в комментариях
для проверки assert(условие)
пример:
#include <cassert>
int findBest(const Data* pData)
{
/// если false, завершить работу программы
assert(0 != pData);
// основной код
}
17.03.2012
cppNewb.ru 15
Обработка исключений в С++
модель с завершением
автоматическое продолжение программы невозможно
обработчик освобождает ресурсы и отдает управление на верхний уровень
механизм обработки опциональный
(опции компилятора)
17.03.2012
cppNewb.ru 16
Идеи обработки исключений
разделить основной код и код обработки сбоев
обрабатывать сбои на том уровне, на котором это может быть сделано
усложнить игнорирование появления сбоев
унифицировать способ передачи информации о сбое
17.03.2012
cppNewb.ru 17
Запуск исключений
в системе создается объект с информацией об исключении, который “запускается” из текущего контекста
“нормальное” исполнение программы прерывается и начинается “обработка исключения”
17.03.2012
cppNewb.ru 18
Источники исключений
обработка аппаратных прерываний
функции стандартной библиотеки
функции “системных” библиотек
пользовательский код
17.03.2012
cppNewb.ru 19
Исключение – что это такое
может быть любого типа (как пользовательского, так и встроенного)
несет информацию (о проблеме)
имя класса (типа) исключения
данные экземпляра исключения
создается и копируется в точке запуска
17.03.2012
cppNewb.ru 20
Запуск исключений (пример)
if (0 == pData)
{
}
или
throw CNullPointer();
if (0 == pData)
{
throw ERR_DATA; // не лучший
}
17.03.2012
cppNewb.ru 21
Локализация блоков с исключениями
try-блок – составная инструкция, при выполнении которой могут генерироваться исключения
try-блок сопровождается одним или несколькими блоками обработки исключений (catch-блоки)
17.03.2012
cppNewb.ru 22
Обработка исключений
обработчик исключений
осуществляет перехват и обработку исключений
располагается сразу после блока try
начинается с ключевого слова catch
может использовать “пойманное” исключение и извлекать из него информацию
17.03.2012
cppNewb.ru 23
Обработка исключений (пример)
try
{
}
// код, который может генерировать исключения
catch (Type1 exept)
{
// обработка исключений типа Type1
}
catch (Type2 exept)
{
// обработка исключений типа Type2
}
// нормальное выполнение программы...
17.03.2012
cppNewb.ru 24
Раскрутка стека
просмотр стека и поиск подходящего обработчика для исключения
по мере раскрутки стека автоматически уничтожаются локальные объекты
порядок разрушения обратный порядку создания (стек программы)
17.03.2012
cppNewb.ru 25
Когда объект создан?
объект считается созданным после завершения работы конструктора
составной объект считается созданным после создания всех входящих в него объектов
массив считается созданным после создания всех его элементов
17.03.2012
cppNewb.ru 26
Автоматическое разрушение
в процессе раскрутки стека производится только для созданных
в массиве только для тех элементов массива, которые были созданы
17.03.2012
cppNewb.ru 27
Поиск подходящего обработчика
просматриваются “ближайшие” обработчики в порядке их следования в исходном коде
объект (ссылка на объект) исключения производного класса перехватывается обработчиком базового класса
при запуске указателя поиск идет по стандартным правила преобразований указателей
17.03.2012
cppNewb.ru 28
Перехват исключения (пример)
class CExep1 {}; class CExep2
: public CExept1
{
public: CExep2(const
CExept1&);
};
void f()
{
throw CExept1();
}
try
{
f();
}
catch (const CExept2&)
{
…
}
catch (const CExept1&)
{
…
}
17.03.2012
cppNewb.ru 29
Преобразования исключений
обработчик объекта базового типа “усекает” исключение производного типа до базового
автоматические преобразования одного типа исключений к другому не производятся
17.03.2012
cppNewb.ru 30
Как перехватывать исключения
по константной ссылке
избегаем копирования объекта исключения
избегаем усечения до родительского типа
гарантируем постоянство объекта исключения
рекомендуется использовать для перехвата константные ссылки
17.03.2012
cppNewb.ru 31
Перехват любых исключений
список аргументов (…)
следует размещать в конце списка перехватчиков
невозможно получить информацию об исключении и его типе
17.03.2012
cppNewb.ru 32
Перехват любых исключений
(пример)
catch (const std::bad_alloc& ex)
{
// обработка
}
catch (...)
{
// обработка
}
17.03.2012
cppNewb.ru 33
Перезапуск исключения
передает исключение далее
необходим, если текущий обработчик не может выполнить всю работу
вызывается throw без аргумента внутри обработчика исключения
17.03.2012
cppNewb.ru 34
Перезапуск исключения (пример)
catch (const CExept1& ex1)
{
// обработка
throw;
}
catch (...)
{
// обработка
throw;
}
17.03.2012
cppNewb.ru 35
Исключение в деструкторе
деструктор вызывается
нормальный вызов
при обработке исключения
при обработке исключение не должно покинуть сам деструктор
17.03.2012
cppNewb.ru 36
Неперехваченные исключения
вызывается terminate()
terminate() по умолчанию вызывает
abort() из системной библиотеки
17.03.2012
cppNewb.ru 37
Вызов terminate
неперехваченное исключение
исключение в деструкторе локального объекта в процессе раскрутки стека
исключение в конструкторе или деструкторе глобального или статического объекта
17.03.2012
cppNewb.ru 38
Спецификация исключений
не рекомендуется использовать
часть объявления функции
список исключений, которые могут быть сгенерированы функцией
пример:
void func(int a) throw(CEx1, CEx2);
17.03.2012
cppNewb.ru 39
Стандартные исключения
образуют иерархию классов
объявлены в пространстве имен std
объявлены в заголовочных файлах
<stdexcept>, <new>, <exception>,
<ios>, <typeinfo>
17.03.2012
cppNewb.ru 40
Стандартные исключения
(фрагмент иерархии)
exception
logic_error
length_error – неверная длина
out_of_range – выход за пределы диапазона
invalid_argument – неверный аргумент
runtime_error
range_error – ошибка диапазона
overflow_error – переполнение
bad_alloc
17.03.2012
cppNewb.ru 41