network_error, painting_error и т.п. Мы обсудим это позже. А до этого давайте рассмотрим, как работают стандартные исключения.

Поскольку стандартная библиотека использует стандартные классы исключений (допустим это), можно ожидать, что классы из стандартной библиотеки будут их выбрасывать при возникновении проблемной ситуации, например при попытке использовать индекс, выходящий за пределы диапазона вектора vector.

std::vector<int> v;

int i = -1;

// заполнить вектор v...

try {

 i = v.at(v.size()); // Выход на один элемент за конец вектора

} catch (std::out_of_range& е) {

 std::cerr << 'Whoa, exception thrown: ' << e.what() << ' ';

}

vector<>::at выбросит исключение out_of_range, если вы используете индекс, значение которого меньше или больше, чем size() - 1. Поскольку вам это известно, вы можете написать обработчик, специально предназначенный для этой исключительной ситуации. Если вам не требуется обрабатывать отдельно конкретный тип исключения, а вместо этого вы предпочли бы одинаково обрабатывать все исключения, вы можете перехватить базовый класс всех исключений.

catch(std::exception& е) {

 std::cerr << 'Nonspecific exception: ' << e.what() << ' ';

}

В результате будет перехватываться любой класс, производный от exception, what — это виртуальная функция-член, которая выдает строку сообщения, зависящую от реализации.

Я почти вернулся в исходную точку. Цель примера 9.1, который сопровождается продолжительным обсуждением, — иллюстрация достоинств класса исключения. Две вещи делают класс исключения полезным: иерархия, отражающая природу исключения, и сообщение, выдаваемое при перехвате исключения и предназначенное для пользователей программы. Иерархия классов исключений позволит разработчикам, использующим вашу библиотеку, создавать безопасный программный код и легко его отлаживать, а текст сообщения позволит тем же самым разработчикам предоставлять конечным пользователям приложения осмысленное сообщение об ошибке.

Исключения представляют собой сложную тему, и безопасная и эффективная обработка исключительных ситуаций является одной из самых трудных задач в проектировании программного обеспечения в целом и на языке C++ в частности. Каким должен быть конструктор, который не приведет к утечке памяти, если исключение выбрасывается в его теле или в списке инициализации? Что такое безопасное исключение? Я отвечу на эти и другие вопросы в последующих рецептах.

9.2. Создание безопасного при исключениях конструктора

Проблема

Ваш конструктор должен обеспечить базовые и строгие гарантии безопасности исключений. См. обсуждение, которое следует за определением «базовых» и «строгих» гарантий.

Решение

Используйте в конструкторе блоки try и catch, чтобы правильно завершить действия по очистке объекта, если в ходе конструирования выбрасывается исключение. В примере 9.2 приводятся простые классы Device и Broker. Broker создает два объекта Device в динамической памяти (heap), но он должен правильно очистить память от этих объектов, если при конструировании выбрасывается исключение.

Пример 9.2. Безопасный при исключениях конструктор

#include <iostream>

#include <stdexcept>

using namespace std;

class Device {

public:

 Device(int devno) {

  if (devno == 2)

   throw runtime_error('Big problem');

 }

 ~Device() {}

};

class Broker {

public:

 Broker (int devno1, int devno2) : dev1_(NULL), dev2_(NULL) {

  try {

   dev1_ = new Device(devno1); // Заключить операторы создания

   dev2_ = new Device(devno2); // объектов в динамической памяти в

                               // блок try ...

  } catch (...) {

   delete dev1_; // ...очистить память и повторно

   throw;        // выбросить исключение, если что-то не

                 // получилось.

  }

 }

 ~Broker() {

  delete dev1_;

  delete dev2_;

 }

private:

 Broker();

 Device* dev1_;

 Device* dev2_;

};

int main() {

 try {

  Broker b(1, 2);

 } catch(exception& e) {

  cerr << 'Exception: ' << e.what() << endl;

 }

}

Обсуждение
Добавить отзыв
ВСЕ ОТЗЫВЫ О КНИГЕ В ИЗБРАННОЕ

0

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

Отметить Добавить цитату