2009-10-15 2 views

ответ

129

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, позволяя всем остальным проходить (и летать дальше по стеку вызовов).

P.S. Разработка полезной иерархии классов исключений (которая позволит вам улавливать только типы исключений, которые вас интересуют в каждой точке вашего кода) является нетривиальной задачей. То, что вы видите в стандартной библиотеке C++, - это один из возможных подходов, предложенный авторами этого языка. Как вы видите, они решили разделить все типы исключений на «ошибки времени выполнения» и «логические ошибки» и позволить вам перейти оттуда со своими собственными типами исключений. Конечно, есть альтернативные способы структурирования этой иерархии, которые могут быть более уместны в вашем дизайне.

Обновление: Переносимость Linux против Windows,

Как Loki Astari и unixman83 отметил в своем ответе и комментариях ниже, конструктор exception класса не принимает никаких аргументов в соответствии со стандартом C++. Microsoft C++ имеет конструктор, принимающий аргументы в классе exception, но это не стандарт. Класс runtime_error имеет конструктор, принимающий аргументы (char*) на обеих платформах, Windows и Linux. Чтобы быть портативным, лучше использовать runtime_error.

(И помните, только потому, что спецификация вашего проекта говорит ваш код не должен работать на Linux, это не значит, что он не делает никогда не придется работать на Linux.)

+0

спасибо. отличный ответ. хотя мне интересно, есть ли когда-либо необходимость иметь различный тип исключения ... просто мысль. – sivabudh

+0

Если существует вероятность того, что исключение может быть повторно покрыто, тогда может быть полезен другой тип исключения, поскольку мы можем использовать механизм обработки исключений, чтобы направить исключение на обработчик, который попытается исправить проблему. Если нет шансов на восстановление, то одно из стандартных исключений - штраф. –

+1

Так же, как и в стороне: нет никакого правила, нигде, что заставляет вас выводить из 'std :: exception'. Конечно, все 'std' вещи бросают производные классы этого, но нет абсолютно никаких оснований только бросать производные объекты std :: exception. – rubenvb

15

станд :: исключение должно быть (обратите внимание на рассмотренную) абстрактную базу стандартной иерархии исключений. Это связано с тем, что в конкретном сообщении нет механизма для передачи (для этого вы должны получить и определить, что()). Нет ничего, что помешало бы вам использовать 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"; 
} 
+1

Спасибо за ответ martin. Однако я использую std :: exception() так же, как описано выше. т. е. конструктор std :: exception() может также принимать std :: string() или const char *. – sivabudh

+12

Не соответствует стандарту. std :: exception имеет один конструктор, который не принимает аргументов. Использование версии, принимающей std :: string или C-String, не переносится. –

+7

Из-за Microsoft я привык бросать 'std :: exception (std :: string)'. Теперь я понимаю, что я должен бросить 'std :: runtime_error', если я хочу, чтобы мой код работал в Linux (GCC). – unixman83

Смежные вопросы