添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

Все исключения в языке C++ описываются типом exception , который определен в заголовочном файле <exception> . И при обработке исключений мы также можем использовать данный класс, интерфейс которого выглядит следующим образом

namespace std class exception public: exception() noexcept; exception(const exception&) noexcept; exception& operator=(const exception&) noexcept; virtual ~exception(); // Destructor virtual const char* what() const noexcept; // возвращает сообщение об исключении

Используем данный тип для обработки исключения:

#include <iostream> double divide(int, int); int main() int x {500}; int y{}; double z = divide(x, y); std::cout << z << std::endl; catch (const std::exception& err) std::cout << "Error!!!" << std::endl; std::cout << "The End..." << std::endl; double divide(int a, int b) if (!b) throw std::exception(); return a / b;

Прежде всего, оператору throw передается объект типа std::exception

throw std::exception();

Если мы хотим отловить исключения типа exception, то нам надо в выражении catch определить переменную этого типа:

catch (const std::exception& err)

То есть здесь err представляет константную ссылку на объект exception. Если мы не собираемся использовать эту переменную в блоке catch, то можно указать просто тип исключения:

catch (std::exception) std::cout << "Error!!!" << std::endl;

С помощью функции what() можно получить сообщение об ошибке в виде строки в С-стиле. Однако непосредственно для типа std::exception он имеет мало смысла, поскольку просто выводит название класса. Но в производных классах он может использоваться для вывода сообщения об ошибке.

Создание производных классов

На основе класса std::exception мы можем создавать свои собственные типы исключений. Например:

#include <iostream> class person_error: public std::exception public: person_error(const std::string& message): message{message} const char* what() const noexcept override return message.c_str(); // получаем из std::string строку const char* private: std::string message; // сообщение об ошибке class Person public: Person(std::string name, unsigned age) if(!age || age > 110) // если age==0 или age > 110 throw person_error("Invalid age"); this->name = name; this->age = age; void print() const std::cout << "Name: " << name << "\tAge: " << age << std::endl; private: std::string name; unsigned age; void testPerson(std::string name, unsigned age) Person person{name, age}; // создаем один объект Person person.print(); catch (const person_error& err) // обработка ошибок, сязанных с Person std::cout << "Person error: " << err.what() << std::endl; catch (const std::exception&) // обработка остальных исключений std::cout << "Something wrong"<< std::endl; int main() testPerson("Tom", 38); // Name: Tom Age: 38 testPerson("Sam", 250); // Person error: Invalid age

Здесь определен класс Person, который представляет пользователя. В конструктор класса передается имя и возраст. Однако передаваемое число может превышать разумный возраст или быть равно нулю. В этом случае мы генерируем исключение типа person_error :

Person(std::string name, unsigned age) if(!age || age > 110) // если age==0 или age > 110 throw person_error("Invalid age");

Класс person_error унаследован от std::exception, через конструктор получает сообщение об ошибке и хранит его в переменной message:

class person_error: public std::exception public: person_error(const std::string& message): message{message} const char* what() const noexcept override return message.c_str(); // получаем из std::string строку const char* private: std::string message; // сообщение об ошибке

Для возвращения сообщения нам надо переопределить виртуальную функцию what() . Но проблема заключается в том, что функция возвращает строку const char* , но класс хранит сообщение в виде строки std::string. И чтобы получить из std::string значение const char* , у строки вызываем функцию c_str()

return message.c_str();     // получаем из std::string строку const char*

Для теста определена функция testPerson, в которой в блоке try создается объект Person. Конструкция try..catch использует два блока catch для обработки исключений. Первый блок обрабатывает исключения производного типа - класса person_error, а последний блок представляет базовый тип exceptionЖ

catch (const person_error& err) // обработка ошибок, сязанных с Person std::cout << "Person error: " << err.what() << std::endl; catch (const std::exception&) // обработка остальных исключений std::cout << "Something wrong"<< std::endl;

И в данном случае программа выдаст следующий результат:

Name: Tom Age: 38 Person error: Invalid age
  • Язык программирования С++
  • Первая программа на Windows. Компилятор g++
  • Первая программа на Windows. Компилятор Clang
  • Первая программа на Linux. Компилятор g++
  • Первая программа на MacOS. Компилятор Clang
  • Настройка параметров компиляции
  • Локализация и кириллица в консоли
  • Глава 2. Основы языка программирования C++
  • Структура программы
  • Переменные
  • Типы данных
  • Константы
  • Ввод и вывод в консоли
  • using. Подключение пространств имен и определение псевдонимов
  • Арифметические операции
  • Статическая типизация и преобразования типов
  • Поразрядные операции
  • Операции присваивания
  • Условные выражения
  • Конструкция if-else и тернарный оператор
  • Конструкция switch-case
  • Циклы
  • Ссылки
  • Массивы
  • Многомерные массивы
  • Массивы символов
  • Введение в строки
  • Глава 3. Указатели
  • Что такое указатели
  • Операции с указателями
  • Арифметика указателей
  • Константы и указатели
  • Указатели и массивы
  • Глава 4. Функции
  • Определение и объявление функций
  • Область видимости объектов
  • Параметры функции
  • Передача аргументов по значению и по ссылке
  • Константные параметры
  • Оператор return и возвращение результата
  • Указатели в параметрах функции
  • Массивы в параметрах функции
  • Параметры функции main
  • Возвращение указателей и ссылок
  • Перегрузка функций
  • Рекурсивные функции
  • Рекурсия на примере быстрой сортировки
  • Указатели на функции
  • Указатели на функции как параметры
  • Тип функции
  • Указатель на функцию как возвращаемое значение
  • Разделение программы на файлы
  • Внешние объекты
  • Глава 5. Динамическая память и smart-указатели
  • Динамические объекты
  • Динамические массивы
  • unique_ptr<T>
  • shared_ptr<T>
  • Глава 6. Объектно-ориентированное программирование
  • Определение классов
  • Конструкторы и инициализация объектов
  • Управление доступом. Инкапсуляция
  • Объявление и определение функций класса
  • Конструктор копирования
  • Константные объекты и функции
  • Ключевое слово this
  • Дружественные функции и классы
  • Статические члены класса
  • Деструктор
  • Структуры
  • Перечисления
  • Наследование
  • Управление доступом в базовых и производных классах
  • Скрытие функционала базового класса
  • Множественное наследование
  • Виртуальные функции и их переопределение
  • Преобразование типов
  • Динамическое преобразование
  • Особенности динамического связывания
  • Чистые виртуальные функции и абстрактные классы
  • Перегрузка операторов
  • Операторы преобразования типов
  • Оператор индексирования
  • Переопределение оператора присваивания
  • Пространства имен
  • Вложенные классы
  • Глава 7. Исключения
  • Обработка исключений
  • Вложенные try-catch
  • Создание своих типов исключений
  • Тип exception
  • Типы исключений
  • Глава 8. Шаблоны
  • Шаблоны функций
  • Шаблон класса
  • Специализация шаблона класса
  • Наследование и шаблоны классов
  • Глава 9. Контейнеры
  • Типы контейнеров
  • Вектор
  • Итераторы
  • Операции с векторами
  • Array
  • Forward_list
  • Deque
  • Стек std::stack
  • Очередь std::queue
  • Очередь приоритетов std::priority_queue
  • Множества
  • Словарь std::map
  • Глава 10. Строки
  • Определение строк
  • Строки с поддержкой Unicode
  • Преобразование типов и строки
  • Сравнение строк
  • Получение подстроки и проверка начала и конца строки
  • Поиск подстроки
  • Изменение строки
  • Операции с символами
  • Программа подсчета слов
  • Тип std:string_view
  • Глава 11. Семантика перемещения
  • rvalue
  • Конструктор перемещения
  • Оператор присваивания с перемещением
  • Роль noexcept при перемещении
  • Глава 12. Объекты функций и лямбда-выражения
  • Объекты функций
  • Лямбда-выражения
  • Захват внешних значений в лямбда-выражениях
  • Шаблон std::function<>
  • Проекция данных
  • Пропуск элементов. drop_view и drop_while_view
  • Извлечение диапазона элементов. take_view и take_while_view
  • Цепочки представлений
  • Глава 14. Ограничения шаблонов
  • Оператор requires
  • Концепты
  • Выражение requires
  • Ограничения типа для auto
  • Глава 15. Потоки и система ввода-вывода
  • Базовые типы для работы с потоками
  • Файловые потоки. Открытие и закрытие
  • Чтение и запись текстовых файлов
  • Переопределение операторов ввода и вывода
  • Глава 16. Стандартная библиотека C++
  • Математические константы и операции
  • Форматирование строк и функция format
  • std::optional<T>
  • Глава 17. Идиомы C++
  • Управление ресурсами. Идиома RAII
  • Идиома копирования и замены
  • Идиома Move-and-Swap
  • Глава 18. Среды разработки
  • Первая программа в Visual Studio
  • Первая программа в Qt Creator
  •