2013-08-27 1 views
7

Я только что прочитал, что в стандартной версии C++ 11 спецификации исключений устарели. Ранее я думал, что указать, что могут бросить ваши функции, - это хорошая практика, но, видимо, не так.Почему спецификации исключений C++ не проверяются во время компиляции?

После прочтения Herb Stutter's well-cited article, я не могу не задаться вопросом: почему на самом деле спецификации спецификации исключений реализованы так, как они есть, и почему комитет решил отказаться от них вместо того, чтобы их проверяли во время компиляции? Почему компилятор даже разрешает бросать исключение, которое не появляется в определении функции? Для меня это звучит так, как будто вы говорите: «Вы, вероятно, не должны указывать свой тип возвращаемой функции, потому что, когда вы укажете int f(), но внутри него ваша программа, вероятно, сработает». (То есть, где концептуальное отличие от сильного печатая?)

(Из-за отсутствия поддержки спецификации исключений в typedef с, учитывая, что синтаксис шаблона, вероятно, Тьюринг-полной, реализуя это звучит достаточно просто.)

+0

Важно отметить, что компиляторы не всегда могут видеть определение. –

+0

Я думаю, что большая причина в том, что он сломает много хорошего кода шаблона. –

+0

(И если вы хотите сделать это дальше, почему компилятор даже разрешит функции доступа к переменным, которые не отображаются в объявлении функции?) –

ответ

-1

Если функция f() throw(int) вызвала функцию g() throw(int, double), что произойдет?

Проверка времени компиляции будет препятствовать тому, чтобы ваша функция вызывала любую другую функцию с менее строгим спецификатором броска, что было бы огромной болью.

+1

, если функция 'int f()' возвращает результат 'double g()' без преобразования, не имея этого повышения, ошибка не будет большой болью, но, что ж, ошибка. И я ничего не сказал о том, чтобы сделать что-то обязательным; всегда можно было объявить 'f()' без спецификатора 'throw' ... – Taral

11

Первоначальная причина заключалась в том, что надежно проверял данное тело существующего кода, а факт , что никакой указатель означает, что что-либо может бросить. Это означает, что если статическая проверка была в силе, следующий код будет не компиляция:

double 
safeSquareRoot(double d) throw() 
{ 
    return d > 0.0 ? sqrt(d) : 0.0; 
} 

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

Единственный реальный случай, когда функция должна знать о исключениях, которые могут возникнуть, - это знать, какие исключения не могут произойти . В частности, невозможно написать код безопасности по потоку , если вы не можете быть уверены, что некоторые функции никогда не будут . Даже здесь статическая проверка неприемлема для описанных выше причин , поэтому спецификация исключения составляет , которая больше похожа на утверждение, которое вы не можете отключить: при написании throw() вы получаете более или менее эквивалент отказ утверждения, если функция прекращена за исключением.

Ситуация на Java несколько отличается. В Java нет реальных параметров, что означает, что если вы не можете использовать коды возврата, если функция также имеет возвращаемое значение. Результатом является то, что исключения используются во многих случаях, когда предпочтительным будет код возврата . И они, у вас есть, чтобы знать, и обрабатывать немедленно. Для вещей, которые должны быть действительно быть исключениями, Java имеет java.lang.RuntimeException (который не проверен, статически или нет).И он не имеет права говорить, что функция никогда не может выбросить исключение; он также использует непроверенные исключения (Error) в случаях, когда отмена программы будет более подходящей.

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