Запуск или перехват особой ситуации отражается на взаимоотношениях функций. Поэтому имеет смысл задавать в описании функции множество особых ситуаций, которые она может запустить:
void f(int a) throw (x2, x3, x4);
В этом описании указано, что f() может запустить особые ситуации x2, x3 и x4, а также ситуации всех производных от них типов, но больше никакие ситуации она не запускает. Если функция перечисляет свои особые ситуации, то она дает определенную гарантию всякой вызывающей ее функции, а именно, если попытается запустить иную особую ситуацию, то это приведет к вызову функции unexpected().
Стандартное предназначение unexpected() состоит в вызове функции terminate(), которая, в свою очередь, обычно вызывает abort(). Подробности даны в §9.7.
По сути определение
void f() throw (x2, x3, x4) { // какие-то операторы }
эквивалентно такому определению
void f() { try { // какие-то операторы } catch (x2) { // повторный запуск throw; } catch (x3) { // повторный запуск throw; } catch (x4) { // повторный запуск throw; } catch (...) { unexpected(); } }
Преимущество явного задания особых ситуаций функции в ее описании перед эквивалентным способом, когда происходит проверка на особые ситуации в теле функции, не только в более краткой записи. Главное здесь в том, что описание функции входит в ее интерфейс, который видим для всех вызывающих функций. С другой стороны, определение функции может и не быть универсально доступным. Даже если у вас есть исходные тексты всех библиотечных функций, обычно желание изучать их возникает не часто.
Если в описании функции не указаны ее особые ситуации, считается, что она может запустить любую особую ситуацию.
int f(); // может запустить любую особую ситуацию
Если функция не будет запускать никаких особых ситуаций, ее можно описать, явно указав пустой список:
int g() throw (); // не запускает никаких особых ситуаций
Казалось было бы логично, чтобы по умолчанию функция не запускала никаких особых ситуаций. Но тогда пришлось бы описывать свои особые ситуации практически для каждой функции Это, как правило, требовало бы ее перетрансляции, а кроме того препятствовало бы общению с функциями, написанными на других языках. В результате программист стал бы стремиться отключить механизм особых ситуаций и писал бы излишние операторы, чтобы обойти их. Пользователь считал бы такие программы надежными, поскольку мог не заметить подмены, но это было бы совершенно неоправдано.