Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Итог_Пособие C++.doc
Скачиваний:
0
Добавлен:
01.07.2025
Размер:
2.03 Mб
Скачать

4.2 Перехват исключений

Для перехвата исключений используется блок try-catch, синтаксис которого (чуть упрощенно) выглядит следующим образом:

try { тело блока }

catch (Тип [декларатор]) {тело обработчика исключений 1}

[catch (Тип [декларатор]) { тело обработчика исключений 2}]

[catch (Тип [декларатор]) { тело обработчика исключений N-1}]

[catch (…) { тело обработчика исключений N}]

Здесь под словом "декларатор" понимается описание формального параметра − аналогично описанию параметров функций.

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

// Пример 4.6 - перехват исключения

int main() {

std::string filename, result;

for(;;) {

std::cout << "Введите имя файла: ";

std::cin >> filename;

try{

result = firstLine(filename);

break;

} catch(FileNotOpenedException) {

std::cout << "Не удалось открыть файл, проверьте путь и попробуйте ещё раз\n";

} catch(...) { // пишется именно так - три точки

std::cout << "Неизвестная ошибка, попробуйте ещё раз\n";

}

}

std::cout << result;

}

Если функция firstLine завершилась успешно, то результат будет записан в переменную result, затем с помощью оператора break произойдёт выход из цикла, и результат будет выведен на консоль.

Если в функции возникло исключение типа FileNotOpenedException, то выполнение тела try будет прервано (оператор break уже не будет выполняться), и управление передастся в первый блок catch.

Заметим, что у нас может возникнуть исключение и другого типа − ведь в функции мы пользуемся классами std::ifstream и std::string, в методах которых могут возбуждаться свои исключения. Для отлова таких исключений предназначен второй блок catch с многоточием, где многоточие говорит о том, что будет поймано исключение любого типа. Например, если размер первой строки файла будет превышать размер доступной оперативной памяти, то будет поймано исключение типа std::bad_alloc.

В рассмотренном примере мы не использовали возможность объявления параметра в catch − нам было достаточно знать лишь тип исключения. Иногда может быть удобно при возбуждении исключения передавать в объекте исключения какую-то дополнительную информацию. Расширим наш пример, чтобы при возникновении исключения можно было узнать, какой именно файл не удалось открыть:

class FileNotOpenedException{

std::string msg;

public:

FileNotOpenedException(const std::string &fileName)

: msg ("Файл не найден " + fileName){}

std::string what() { return msg; }

};

Теперь оператор throw в нашей функции нужно записывать следующим образом: throw FileNotOpenedException(fileName);

Первый блок catch в функции main теперь будет выглядеть так:

catch(FileNotOpenedException &e) {std::cout << e.what() << std::endl;}

Параметр e передаётся по ссылке, чтобы не тратить лишнее время и память на создание копии объекта (аналогично передаче параметров функций).

Примечание. Заметим, что можно было бы не писать наш класс FileNotOpenedException с нуля, а унаследовать его от одного из стандартных классов исключений − при этом размер кода был бы чуть меньше. Об этом смотрите далее в этой главе.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]