Типы исключений

Последнее обновление: 18.03.2023

Кроме типа exception в C++ есть еще несколько производных типов исключений, которые могут использоваться при различных ситуациях. Основные из них:

  • runtime_error: общий тип исключений, которые возникают во время выполнения

  • range_error: исключение, которое возникает, когда полученный результат превосходит допустимый диапазон

  • overflow_error: исключение, которое возникает, если полученный результат превышает допустимый диапазон

  • underflow_error: исключение, которое возникает, если полученный в вычислениях результат имеет недопустимое отрицательное значение (выход за нижнюю допустимую границу значений)

  • logic_error: исключение, которое возникает при наличии логических ошибок к коде программы

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

  • invalid_argument: исключение, которое возникает при передаче в функцию некорректного аргумента

  • length_error: исключение, которое возникает при попытке создать объект большего размера, чем допустим для данного типа

  • out_of_range: исключение, которое возникает при попытке доступа к элементам вне допустимого диапазона

Типы исключений в C++ и std::exception

Многие стандартные типы исключений делятся на две группы в зависимости от базового класса - logic_error или runtime_error. Большинство этих типов определено в заголовочном файле <stdexcept>

Типы, основанные на logic_error, предназначены для ошибок, которые могли быть обнаружены до выполнения программы и являются следствием неправильной логики программы. Например, ввызов функции с одним или несколькими недопустимыми аргументами или вызов функции-члена для объекта, состояние которого не соответствует требованиям для этой конкретной функции. Вместо обработки подобных исключений можно явно проверять допустимость аргументов или состояние объекта перед вызовом функции.

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

Конструкция try...catch может использовать несколько блоков catch для обработки различных типов исключений. При возникновении исключения для его обработки будет выбран тот, который использует тип возникшего исключения.

При использовании нескольких блоков catch вначале помещаются блоки catch, которые обрабатывают более частные исключения, а только потом блоки catch с более общими типами исключений:

#include <iostream>
 
class Person
{
public:
    Person(std::string name, unsigned age)
    {
        if(name.length() > 11)
            throw std::length_error("Name must be less than 10 chars");
        if(!age || age > 110)
            throw std::range_error("Age must be between 1 and 110");
        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)
{
    try
    {
        Person person{name, age};   // создаем один объект Person
        person.print();
    }
    catch (const std::length_error& ex)
    {
        std::cout << "Length_error: " << ex.what() << std::endl;
    }
    catch (const std::range_error& ex)
    {
        std::cout << "Range_error: " << ex.what() << std::endl;
    }
    catch (const std::exception&)
    {
        std::cout << "Something wrong"<< std::endl;
    }
}
int main()
{
    testPerson("Tom", 38);  // Name: Tom       Age: 38
    testPerson("Gai Yulii Cezar", 42);  // Length_error: Name must be less than 10 chars
    testPerson("Sam", 250);  // Range_error: Age must be between 1 and 110
}

Здесь определен класс Person, в конструктор которого передаем строку-имя и число-возраст пользователя. Но передаваемые данные могут быть некорректными. Например, для допустимого возраста установим пределельный диапазон 1-110, а имя не должно быть длинее 11 символов. И в конструкторе проверяем переданные значения и генерируем различные исключения:

Person(std::string name, unsigned age)
{
    if(name.length() > 11)
        throw std::length_error("Name must be less than 10 chars");
    if(!age || age > 110)
        throw std::range_error("Age must be between 1 and 110");
    this->name = name;
    this->age = age;
}

Для теста определена функция testPerson, в которой в блоке try создается объект Person. Конструкция try..catch использует три блока catch для разных типов исключений. Причем последний блок представляет самый общий тип исключений exception. Второй блок обрабатывает исключения типа range_error, производный от runtime_error. А первый блок обрабатывает исключения типа length_error, который является производным от logic_error.

catch (const std::length_error& ex)
{
    std::cout << "Length_error: " << ex.what() << std::endl;
}
catch (const std::range_error& ex)
{
    std::cout << "Range_error: " << ex.what() << std::endl;
}
catch (const std::exception&)
{
    std::cout << "Something wrong"<< std::endl;
}

С помощью функции what() в блоках catch возвращаем информацию об ошибке. И в данном случае программа выдаст следующий результат:

Name: Tom       Age: 38
Length_error: Name must be less than 10 chars
Range_error: Age must be between 1 and 110
Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850