Одна из причин, по которой исключение исключений устарела, заключается в следующем. Рассмотрим следующий код:
#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(...)
блок.
Это только одна из причин, почему спецификации считаются «плохой практикой» и были устаревшими из-за такого нарушения кода. Есть еще несколько надуманных примеров, и поиск в вашей любимой поисковой системе показывает некоторые очень хорошие ответы.
«Признано, что в C++, например, если метод генерирует исключение, он должен быть объявлен» - вы уверены в этом? – user2357112
@ user2357112 Во всяком случае, исключение должно быть поймано или объявлено ... Какова ваша мысль? – zell
@zell Вы имеете в виду указать, какое исключение может вызвать функция? Это устарело, за исключением 'noexcept' в C++ 11 или' throw() 'в C++ 98/03. – vsoftco