Відповіді:
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
Клас має конструктор , який приймає аргументи ( char*
) на обох платформах, Windows , і Linux. Щоб бути портативним, краще використовуйте runtime_error
.
(І пам’ятайте, тільки тому, що специфікація вашого проекту говорить, що ваш код не повинен працювати в Linux, це не означає, що він ніколи не повинен працювати в Linux.)
std::exception
. Звичайно, всі std
речі кидають похідні класи цього, але немає абсолютно ніяких причин лише кидати std::exception
похідні об'єкти.
std::exception
слід вважати (зауважте, що розглядається) абстрактною базою стандартної ієрархії винятків. Це тому, що не існує механізму для передачі певного повідомлення (для цього потрібно вивести і спеціалізуватися what()
). Ніщо не заважає вам використовувати std :: виключення, і для простих додатків це може бути все, що вам потрібно.
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).