2015-04-09 3 views
-3

Признано, что в C++, например, если метод генерирует исключение, он должен быть объявлен.  Но убедительная причина, по которой такое правило применяется, кажется, менее известна для некоторых людей (я спросил некоторых коллег, никаких убедительных ответов).Почему исключение должно быть объявлено?

Может ли кто-нибудь объяснить мне, возможно, со стороны компилятора, почему мы абсолютно должны объявлять исключение в методах, которые его бросают? Благодарю.

+0

«Признано, что в C++, например, если метод генерирует исключение, он должен быть объявлен» - вы уверены в этом? – user2357112

+0

@ user2357112 Во всяком случае, исключение должно быть поймано или объявлено ... Какова ваша мысль? – zell

+3

@zell Вы имеете в виду указать, какое исключение может вызвать функция? Это устарело, за исключением 'noexcept' в C++ 11 или' throw() 'в C++ 98/03. – vsoftco

ответ

2

Как вы писали эти слова: не нужно необходимо указать спецификации исключений для функций (через throw(), которые устарели в C++ 11). Это требование Java (например, проверенные исключения, поскольку они называются).

Однако, что вы можете сделать в C++ 11, это функции метки noexcept, что означает, что они не будут выбрасывать. Это дает компилятору некоторую свободу для оптимизации некоторых вещей, которые в противном случае они не смогут, поскольку он не знает, может ли функция выбраться или нет. Последствия использования спецификаций noexcept для функций будут заключаться в том, что если они каким-то образом бросят, будет называться std::terminate, эффективно «разбивая» ваше приложение. Надеюсь это поможет.

+0

Спасибо. Я чему-то научился. – zell

+3

Обратите внимание, что 'noexcept' также означает, что если функция действительно позволяет исключить исключение, перейдите непосредственно к' terminate', перейдите прямо к 'terminate', не пропустите Go, не заберите $ 200. –

1

Одна из причин, по которой исключение исключений устарела, заключается в следующем. Рассмотрим следующий код:

#include <iostream> 

void h() // no exception specification 
{ 
    throw double(0); // throws double 
} 

void f() throw(int) 
{ 
    h(); // suppose we were sure that h() doesn't throw 
} 

int main() 
{ 
    try 
    { 
     f(); 
    } 
    catch (int) 
    { 
     std::cout << "int exception caught" << std::endl; 
    } 
    catch (...) 
    { 
     std::cout << "Other exception caught" << std::endl; 
    } 
} 

Предположим, что мы считаем, что f() только бросает int, поэтому мы указываем это через спецификации исключений. Тем не менее, f() использует некоторую стороннюю библиотечную функцию h(), с которой у нас нет контроля (здесь мы определили ее, но в реальном коде вы можете предположить, что h() вызывается через общую библиотеку). Теперь, в вер. 0,1 библиотеки, мы знали, что h() не выбрасывают (или могут бросить только int), поэтому мы можем безопасно использовать его в нашем коде для f(). Тем не менее, разработчики библиотеки считали, что это хорошая идея, чтобы бросить в некоторых случаях double, поэтому они изменили h() который теперь бросает double (и мы слепо обновили нашу библиотеку, так что теперь у нас есть «новый» h().

сейчас вы видите, что произойдет:.. h() бросает double внутри f() Однако f() отмечен как throw(int), так что все ставки выключены, программа заканчивается вызовом terminate, бац

Обратите внимание, что, не определяя при всех throw(int), мы мог бы поймать исключение double через последние catch(...) блок.

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

+0

Ну, это технически называет «неожиданным», который вызывает соответствующий обработчик, который по умолчанию «завершает». –

+0

@ T.C. правильно, отредактировано. – vsoftco

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