Виключення в конструкторах та деструкторах
11. Ієрархія виключень.
Существует два типа исключений: исключения, созданные исполняемой программой, и исключения, созданные общеязыковой средой выполнения. Кроме того, существует иерархия исключений, которые могут быть созданы приложением или средой выполнения.
Класс Exception является базовым классом для исключений. Несколько классов исключений наследуются непосредственно от Exception, в том числеApplicationException и SystemException. Эти два класса образуют основу почти для всех исключений среды выполнения.
Большинство исключений, полученных непосредственно из Exception, не добавляют функциональность к классу Exception. Например, иерархия класса InvalidCastException следующая:
Object Исключение SystemException InvalidCastException
Среда выполнения создает соответствующий производный класс SystemException при возникновении исключения. Эти ошибки возникают в результате сбоев при проверках, выполняемых средой выполнения (таких как ошибки выхода массива за границы диапазона), и могут возникать при выполнении любого метода. При разработке приложения, порождающего новые исключения, такие исключения следует создавать из класса Exception. Не рекомендуется перехватывать исключение SystemException или создавать исключение SystemException в пользовательских приложениях.
Наиболее серьезные исключения (создаются средой выполнения или в результате неустранимых условий) включают в себя ExecutionEngineException,StackOverflowException и OutOfMemoryException.
Исключения взаимодействия являются производными от SystemException и расширяются классом ExternalException. Например, COMException — это исключение, порождаемое в ходе операций COM-взаимодействия, производное от ExternalException. Классы Win32Exception и SEHException также являются наследниками ExternalException.
Иерархия исключений среды выполнения
Среда выполнения имеет базовый набор исключений, производных от класса SystemException, которые порождаются при выполнении отдельных инструкций. В следующей таблице приведен список иерархии стандартных исключений, предоставляемых средой выполнения, а также указаны те условия, при которых следует создавать производный класс.
Тип исключения | Базовый тип | Описание | Пример |
Исключение | Объект | Базовый класс для всех исключений. | Отсутствует (используйте класс, производный от этого исключения). |
SystemException | Исключение | Базовый класс для всех ошибок, созданных средой выполнения. | Отсутствует (используйте класс, производный от этого исключения). |
IndexOutOfRangeException | SystemException | Генерируется средой выполнения только при неправильной индексации массива. | Индексирование массива вне его действительного диапазона: arr[arr.Length+1] |
NullReferenceException | SystemException | Создается средой выполнения только при ссылке на пустой объект. | object o = null; o.ToString(); |
AccessViolationException | SystemException | Создается средой выполнения только при доступе к недопустимому участку памяти. | Возникает при взаимодействии с неуправляемым кодом или с небезопасным управляемым кодом, а также при использовании неправильного указателя. |
InvalidOperationException | SystemException | Генерируется методами в случае недопустимого состояния. | Вызов Enumerator.GetNext() после удаления Item из соответствующей коллекции. |
ArgumentException | SystemException | Базовый класс для всех исключений аргументов. | Отсутствует (используйте класс, производный от этого исключения). |
ArgumentNullException | ArgumentException | Генерируется методами, для которых не допускается пустое значение аргументов. | String s = null; "Calculate".IndexOf (s); |
ArgumentOutOfRangeException | ArgumentException | Генерируется методами, проверяющими принадлежность аргументов к заданному диапазону. | String s = "string"; s.Chars[9]; |
ExternalException | SystemException | Базовый класс для исключений, происходящих или предназначенных для сред вне среды выполнения. | Отсутствует (используйте класс, производный от этого исключения). |
ComException | ExternalException | Исключение, инкапсулирующее сведения HRESULT COM. | Используется при взаимодействии COM. |
SEHException | ExternalException | Исключение, инкапсулирующее структурированные данные обработки исключений Win32. | Используется в операциях с неуправляемым кодом. |
12. Поняття шаблону функцій.
Шабло́ны (англ. template) — средство языка C++, предназначенное для кодирования обобщённых алгоритмов, без привязки к некоторым параметрам (например, типам данных, размерам буферов, значениям по умолчанию).
В C++ возможно создание шаблонов функций и классов.
Шаблоны позволяют создавать параметризованные классы и функции. Параметром может быть любой тип или значение одного из допустимых типов (целое число, enum, указатель на любой объект с глобально доступным именем). Например, нам нужен какой-то класс:
class SomeClass{
int SomeValue;
int SomeArray[20];
...
}
Для одной конкретной цели мы можем использовать этот класс. Но, вдруг, цель немного изменилась, и нужен еще один класс. Теперь нужно 30 элементов массиваSomeArray и вещественный тип SomeValue и элементов SomeArray. Тогда мы можем абстрагироваться от конкретных типов и использовать шаблоны с параметрами. Синтаксис: в начале перед объявлением класса напишем слово template и укажем параметры в угловых скобках. В нашем примере:
template < int ArrayLength, typename SomeValueType > class SomeClass{
SomeValueType SomeValue;
SomeValueType SomeArray[ ArrayLength ];
...
}
Тогда для первой модели пишем:
SomeClass < 20, int > SomeVariable;
для второй:
SomeClass < 30, double > SomeVariable2;
Хотя шаблоны предоставляют краткую форму записи участка кода, на самом деле их использование не сокращает исполнимый код, так как для каждого набора параметров компилятор создаёт отдельный экземпляр функции или класса.
Шаблоны функций
Синтаксис описания шаблона
Шаблон функции начинается с ключевого слова template, за которым в угловых скобках следует список параметров. Затем следует объявление функции:
template< typename T >
void sort( T array[], int size ); // прототип: шаблон sort объявлен, но не определён
template< typename T >
void sort( T array[], int size ) // объявление и определение
{
T t;
for (int i = 0; i < size - 1; i++)
for (int j = size - 1; j > i; j--)
if (array[j] < array[j-1])
{
t = array[j];
array[j] = array[j-1];
array[j-1] = t;
}
}
template< int BufferSize > // целочисленный параметр
char* read()
{
char *Buffer = new char[ BufferSize ];
/* считывание данных */
return Buffer;
}
Ключевое слово typename появилось сравнительно недавно, поэтому стандарт[1] допускает использование class вместо typename:
template< class T >
Вместо T допустим любой другой идентификатор.
13. Перевантаження та спеціалізація шаблону функцій.
Перегрузка шаблонов функций
Шаблоны функций можно перегружать точно так же, как обычные функции. Два шаблона могут иметь одно и то же имя, если их можно различить по списку параметров, например:
// Возвращает больший из двух аргументов.
template <class Т> Т Мах(Т а, Тb) {
return а > b? а : b;
// Возвращает наибольший элемент массива. template <class Т> Т Мах(Т аrr[], size_t size)
(
Т maxVal = arr[0] ;
for(int i=l; i<size; i++) if (arr[i] > maxVal) maxVal = arr[i];
return maxVal;
}
Специализация шаблона функции
Несколько напоминает перегрузку шаблонов ситуация, когда определяется обычная функция, имя которой совпадает с именем шаблона и список параметров которой соответствует шаблону с некоторым специфическим набором фактических типов. Такую функцию называют специализированной функцией шаблона. Этот прием применяют, когда для некоторого типа или набора типов общий шаблон работать не будет.
Допустим, мы хотим, чтобы шаблон Мах()из последнего примера порождал функцию для двух аргументов-строк, которая возвращала бы большую из них (в смысле алфавитного порядка). Функция Мах (char*, char*), порожденная из первого шаблона, сравнивала бы адреса строк вместо их содержимого. Поэтому нужно определить отдельную функцию Мах (char*, char*):
char *Max(char *a, char *b) {
return strcmp(a, b) > 0? а : b;
}
Когда компилятор встречает вызов какой-то функции, для его разрешения он следует такому алгоритму:
· Сначала ищется обычная функция с соответствующими параметрами.
· Если таковой не найдено, компилятор ищет шаблон, из которого можно было бы генерировать функцию с точным соответствием параметров.
· Если этого сделать невозможно, компилятор вновь рассматривает обычные функции на предмет возможных преобразований типа параметров.
14. Поняття шаблону класів.
Шаблоны классов. Аналогично шаблонам функций. определяется шаблон семейства классов:
template <список_параметров_шаблона> определение_класса
Шаблон семейства классов определяет способ построения отдельных классов подобно тому, как класс определяет правила построения и формат отдельных объектов. В определении класса, входящего в шаблон, особую роль играет имя класса. Оно является не именем отдельного класса, а параметризованным именем семейства классов.
Как и для шаблонов функций, определение шаблона класса может быть только глобальным.
имя_параметризованного_класса <фактические_параметры_шаблона>
имя_объекта (параметры_конструктора);
15. Конкретизація та спеціалізація шаблонів класів.
16. Контейнери бібліотеки STL. Види контейнерів. Загальні поля та методи контейнерів. Ітератори.
Контейнеры
Контейнеры библиотеки STL можно разделить на четыре категории: последовательные, ассоциативные, контейнеры-адаптеры и псевдоконтейнеры.
Контейнер | Описание |
Последовательные контейнеры | |
vector | C-подобный динамический массив произвольного доступа с автоматическим изменением размера при добавлении/удалении элемента. Доступ по индексу за . Добавление-удаление элемента в конец vector занимает амортизированное время, та же операция в начале или середине vector — . Стандартная быстрая сортировка за . Поиск элемента перебором занимает . Существует специализация шаблона vector для типа bool, которая требует меньше памяти за счёт хранения элементов в виде битов, однако она не поддерживает всех возможностей работы с итераторами. |
list | Двусвязный список, элементы которого хранятся в произвольных кусках памяти, в отличие от контейнера vector, где элементы хранятся в непрерывной области памяти. Поиск перебором медленнее, чем у вектора из-за большего времени доступа к элементу. Доступ по индексу за . В любом месте контейнера вставка и удаление производятся очень быстро — за . |
deque | Дэк. Контейнер похож на vector, но с возможностью быстрой вставки и удаления элементов на обоих концах за . Реализован в виде двусвязанного списка линейных массивов. С другой стороны, в отличие от vector, дек не гарантирует расположение всех своих элементов в непрерывном участке памяти, что делает невозможным безопасное использование арифметики указателей для доступа к элементам контейнера. |
Ассоциативные контейнеры | |
set | Упорядоченное множество уникальных элементов. При вставке/удалении элементов множества итераторы, указывающие на элементы этого множества, не становятся недействительными. Обеспечивает стандартные операции над множествами типа объединения, пересечения, вычитания. Тип элементов множества должен реализовывать оператор сравнения operator< или требуется предоставить функцию-компаратор. Реализован на основе самобалансирующего дерева двоичного поиска. |
multiset | То же что и set, но позволяет хранить повторяющиеся элементы. |
map | Упорядоченный ассоциативный массив пар элементов, состоящих из ключей и соответствующих им значений. Ключи должны быть уникальны. Порядок следования элементов определяется ключами. При этом тип ключа должен реализовывать оператор сравнения operator<, либо требуется предоставить функцию-компаратор. |
multimap | То же что и map, но позволяет хранить несколько одинаковых ключей. |
Контейнеры-адаптеры | |
stack | Стек — контейнер, в котором добавление и удаление элементов осуществляется с одного конца. |
queue | Очередь — контейнер, с одного конца которого можно добавлять элементы, а с другого — вынимать. |
priority_queue | Очередь с приоритетом, организованная так, что самый большой элемент всегда стоит на первом месте. |
Псевдоконтейнеры | |
bitset | Служит для хранения битовых масок. Похож на vector<bool> фиксированного размера. Размер фиксируется тогда, когда объявляется объект bitset. Итераторов в bitset нет. Оптимизирован по размеру памяти. |
basic_string | Контейнер, предназначенный для хранения и обработки строк. Хранит в памяти элементы подряд единым блоком, что позволяет организовать быстрый доступ ко всей последовательности. Элементы должны быть POD'ами. Определена конкатенация с помощью +. |
valarray | Шаблон служит для хранения числовых массивов и оптимизирован для достижения повышенной вычислительной производительности. В некоторой степени похож на vector, но в нём отсутствует большинство стандартных для контейнеров операций. Определены операции над двумя valarray и над valarray и скаляром (поэлементные). Эти операции возможно эффективно реализовать как на векторных процессорах, так и на скалярных процессорах с блоками SIMD. |
В контейнерах для хранения элементов используется семантика передачи объектов по значению. Другими словами, при добавлении контейнер получает копию элемента. Если создание копии нежелательно, то используют контейнер указателей на элементы. Присвоение элементов реализуется с помощью оператора присваивания, а их разрушение происходит с использованием деструктора. В таблице приведены основные требования к элементам в контейнерах:
Метод | Описание | Примечание |
Конструктор копии | Создает новый элемент, идентичный старому | Используется при каждой вставке элемента в контейнер |
Оператор присваивания | Заменяет содержимое элемента копией исходного элемента | Используется при каждой модификации элемента |
Деструктор | Разрушает элемент | Используется при каждом удалении элемента |
Конструктор по умолчанию | Создает элемент без аргументов | Применяется только для определенных операций |
operator== | Сравнивает два элемента | Используется при выполнении operator== для двух контейнеров |
Итераторы
В библиотеке STL для доступа к элементам в качестве посредника используется обобщённая абстракция, именуемая итератором. Каждый контейнер поддерживает «свой» вид итератора, который представляет собой «модернизированный» интеллектуальный указатель, «знающий» как получить доступ к элементам конкретного контейнера. Стандарт C++ определяет пять категорий итераторов, описанных в следующей таблице:
Категория | Поддерживаемые операции | Примечание |
Входные | operator++, operator*, operator->, конструктор копии, operator=, operator==, operator!= | Обеспечивают доступ для чтения в одном направлении. Позволяют выполнить присваивание или копирование с помощью оператора присваиваивания и конструктора копии |
Выходные | operator++, operator*, конструктор копии | Обеспечивают доступ для записи в одном направлении. Их нельзя сравнивать на равенство. |
Однонаправленные | operator++, operator*, operator->, конструктор копии, конструктор по умолчанию, operator=, operator==, operator!= | Обеспечивают доступ для чтения и записи в одном направлении. Позволяют выполнить присваивание или копирование с помощью оператора присваиваивания и конструктора копии. Их можно сравнивать на равенство. |
Двунаправленные | operator++, operator--, operator*, operator->, конструктор копии, конструктор по умолчанию, operator=, operator==, operator!= | Поддерживают все функции, описанные для однонаправленных итераторов (см. выше). Кроме того, они позволяют переходить к предыдущему элементу. |
Произвольного доступа | operator++, operator--, operator*, operator->, конструктор копии, конструктор по умолчанию, operator=, operator==, operator!=, operator+, operator-, operator+=, operator-=, operator<, operator>, operator<=, operator>=, operator[] | Эквивалентны обычным указателям: поддерживают арифметику указателей, синтаксис индексации массивов и все формы сравнения. |
17. Послідовні контейнери. Характеристика операцій, що підтримуються послідовними контейнерами.