В чем разница между std::runtime_error
и std::exception
? Как правильно использовать каждый? Почему они вообще разные?
источник
В чем разница между std::runtime_error
и std::exception
? Как правильно использовать каждый? Почему они вообще разные?
std::exception
- это класс, единственная цель которого - служить базовым классом в иерархии исключений. Другого применения он не имеет. Другими словами, концептуально это абстрактный класс (даже если он не определен как абстрактный класс в значении термина C ++).
std::runtime_error
- это более специализированный класс, наследующий от std::exception
, предназначенный для вызова в случае различных ошибок времени выполнения . У него двойное назначение. Он может быть вызван сам по себе или может служить базовым классом для различных, даже более специализированных типов исключений ошибок времени выполнения, таких как std::range_error
и std::overflow_error
т. Д. Вы можете определить свои собственные классы исключений, производные от std::runtime_error
, а также вы можете определить свое собственное исключение. классы, производные от std::exception
.
Точно так же, как std::runtime_error
и стандартная библиотека std::logic_error
, которая также происходит от std::exception
.
Смысл такой иерархии - дать пользователю возможность использовать всю мощь механизма обработки исключений C ++. Поскольку предложение catch может перехватывать полиморфные исключения, пользователь может писать предложения catch, которые могут перехватывать типы исключений из определенного поддерева иерархии исключений. Например, catch (std::runtime_error& e)
перехватит все исключения из std::runtime_error
поддерева, позволяя всем остальным проходить через них (и лететь дальше по стеку вызовов).
PS Создание полезной иерархии классов исключений (которая позволит вам перехватывать только те типы исключений, которые вам интересны в каждой точке вашего кода) - нетривиальная задача. То, что вы видите в стандартной библиотеке C ++, - это один из возможных подходов, предложенных вам авторами языка. Как видите, они решили разделить все типы исключений на «ошибки времени выполнения» и «логические ошибки» и позволить вам продолжить работу с собственными типами исключений. Конечно, существуют альтернативные способы структурирования этой иерархии, которые могут быть более подходящими для вашего дизайна.
Обновление: переносимость Linux и Windows
Как отметили Локи Астари и unixman83 в своем ответе и комментариях ниже, конструктор exception
класса не принимает никаких аргументов в соответствии со стандартом C ++. В Microsoft C ++ есть конструктор, принимающий аргументы в exception
классе, но это нестандартно. У runtime_error
класса есть конструктор, принимающий arguments ( char*
) на обеих платформах, Windows и Linux. Чтобы быть портативным, лучше использовать runtime_error
.
(И помните, что если в спецификации вашего проекта указано, что ваш код не должен работать в Linux, это не означает, что он никогда не должен работать в Linux.)
std::exception
. Конечно, всеstd
вещи бросают производные классы этого, но нет абсолютно никаких причин бросать толькоstd::exception
производные объекты.std::exception
следует считать (обратите внимание на рассмотренное) абстрактной базой стандартной иерархии исключений. Это потому, что нет механизма для передачи определенного сообщения (для этого вы должны получить и специализироватьсяwhat()
). Ничто не мешает вам использовать std :: exception, а для простых приложений это может быть все, что вам нужно.std::runtime_error
с другой стороны, есть допустимые конструкторы, которые принимают строку как сообщение. Когдаwhat()
вызывается, возвращается указатель const char, который указывает на строку C, которая имеет ту же строку, что была передана в конструктор.источник
std::exception(std::string)
. Теперь я понимаю, что должен бросить,std::runtime_error
если хочу, чтобы мой код работал в Linux (GCC).