Обработка ошибок в конструкторах и деструкторах

Несмотря на невозможность конструктора возвращать значение, вы можете из него сгенерировать исключение.

С помощью исключения нетрудно уведомить клиента о результате выполнения конструктора: успешном или нет.

Здесь, однако, есть одна существенная проблема: если исключение "покидает" пределы конструктора, то деструктор для созданного объекта никогда не будет вызван.

Рассмотрим пример конструктора класса, модифицированного с использованием обработки исключения:

GameBoard::GameBoard(int inWidth, int inHeight) throw (bad_alloc): mWidth(inWidth), mHeight(inHeight) {

int i, j;

mCells = new GamePiece* [mWidth];

try {

for (i = 0; i <mWidth; i++) {

mCells[i] = new GamePiece[mHeight];

}

} catch (...) {

/* Освобождаем память, которую мы уже выделили, поскольку деструктор для объекта никогда не будет вызван. Верхняя граница Еог-цикла соответствует индексу последнего элемента в массиве тСе11в, который мы пытались создать динамически (но попытка "проваливается"). Мы должны освободить память с помощью указателей, которые мы успели сохранить в массиве до возникновения исключения, используя все "занятые" индексы этого массива */

for (j = 0; j < i; j++) {delete [] mCells [j ] ;}

delete[] mCells;

//Любое исключение приводим к типу bad_alloc

throwbadalloc();

}

}

Необходимо обрабатывать все ошибочные ситуации, возникающие в самих деструкторах. Причины:

· Деструкторы могут работать, пока обрабатывается другое исключение. Если сгенерировать исключение из деструктора в то время, пока еще активно другое исключение, программа будет завершена.

· Подумайте о своих клиентах. Клиенты не вызывают деструкторы явно: они вызывают оператор delete, который вызывает деструктор. Если вы сгенерируете исключение из деструктора, то какие действия должен, по вашему, предпринять?

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

Поэтому нужно стараться делать деструкторы как модно более простыми. Например, использовать только функции delete и delete[], которые не могут кинуть исключения.

Шаблоны

Шаблоны позволяют параметризовать не только значения, но и типы, позволяют применять классы к разным типам объектов.

С помощью шаблонов можно написать код, который не будет зависеть не только от задаваемых значений, но и от типов этих значений!

Например, вместо создания отдельных классов-стеков для хранения int-значений, объектов типа char и double, можно написать одно определение стекового класса, которое будет использоваться для любого из этих типов.

По историческим причинам для задания параметров-типов шаблона вместо ключевого слова typename можно использовать ключевое слово class. В результате во многих книгах и программах используется такой синтаксис: template<class Т>.

Спецификатор template действует всю последующую инструкцию.

Пример:

template<typename T>

class matrix{

T** _array;

int _width;

int _height;

public:

matrix(int width; int height);

operator+(matrix<T>);

matrix(const matrix<T>&);

};

Шаблонных параметров может быть несколько: template<typenameT, typenameU>

В качестве шаблонных параметров может быть задан размер матрицы

Тогда matrix<int, 4, 5> и matrix<int, 6, 7> - объекты разных классов.

!константные параметры должны быть в конце описания.

Для каждого параметра шаблона выполняется своя компиляция. То есть, при объявлении в коде программы объектов классов A<int> и A<char>, компилятор создаст 2 совершенно разных класса – один для типа int, а второй для типа char

Например, конструктор копирования может принимать в себя также шаблонный параметр:

template<typename T>

class matrix{

public:

template<typename U>

matrix(const matrix<U>&);

};

В описании конструктора будем выполнять приведение типа U к T.

STL: итераторы

Что такое итераторы?

Итератор – обобщенная абстракия, используемая для доступа к элементам контейнера.

Итератор можно представить себе как указатель на определенный элемент контенера.

Какие бывают итераторы?

Обработка ошибок в конструкторах и деструкторах - student2.ru

Все стандартные контейнеры поддерживают либо двунаправленные итераторы, либо итераторы произвольного доступа.

Наши рекомендации