Все исключения в языке 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