C++ 3d.Комментарии

7b6e9298

Проверка спецификаций исключений


Спецификация исключений не является частью типа функции, и typedef не может ее содержать.

Сразу же возникает вопрос: в чем причина этого неудобного ограничения? Д-р Страуструп пишет по этому поводу следующее:

The reason is the exception spacification is not part of the type; it is a constraint that is checked on assignment and exforced at run time (rather than at compile time). Some people would like it to be part of the type, but it isn't. The reason is to avoid difficulties when updating large systems with parts from different sources. See "The Design and Evolution of C++" for details.

Причина в том, что спецификации исключений не являются частью типа; данное ограничение проверяется при присваивании и принудительно обеспечивается во время выполнения (а не во время компиляции). Некоторым людям хотелось бы, чтобы спецификации исключений были частью типа, но это не так. Причина в том, что мы хотим избежать трудностей, возникающих при внесении изменений в большие системы, состоящие из отдельных частей полученных из разных источников. Обратитесь к книге "Дизайн и эволюция C++" за деталями.

По моему мнению, спецификации возбуждаемых исключений -- это одна из самых неудачных частей определения C++. Исторически, неадекватность существующего механизма спецификации исключений обусловлена отсутствием реального опыта систематического применения исключений в C++ (и возникающих при этом вопросов exception safety) на момент их введения в определение языка. К слову сказать, о сложности проблемы говорит и тот факт, что в Java, появившемся заметно позже C++, спецификации возбуждаемых исключений так же реализованы неудачно.

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

Так, например, можно ввести ключевое слово nothrow:


    // ключевое слово nothrow отсутствует: // f() разрешено возбуждать любые исключения прямо или косвенно void f() { // ... }

    // f() запрещено возбуждать любые исключения прямо или косвенно, // проверяется на этапе компиляции void f() nothrow

    { // ... }

    void f() {

    // здесь можно возбуждать исключения прямо или косвенно

    nothrow { // nothrow-блок

    // код, находящийся в данном блоке никаких исключений возбуждать // не должен, проверяется на этапе компиляции

    }

    // здесь снова можно возбуждать исключения

    }

    Еще одним неудачным решением является возможность возбуждать исключения любых (даже встроенных!) типов. Правильным решением является введение специального базового класса для всех возбуждаемых исключений с изначально заложенной в нем специфической функциональностью.


    Содержание раздела