Ответы:
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, которая имеет ту же строку, что была передана в конструктор.
try
{
if (badThingHappened)
{
throw std::runtime_error("Something Bad happened here");
}
}
catch(std::exception const& e)
{
std::cout << "Exception: " << e.what() << "\n";
}
std::exception(std::string). Теперь я понимаю, что должен бросить, std::runtime_errorесли хочу, чтобы мой код работал в Linux (GCC).