►Зачем, нужен новый механизм обработки ошибок...291

We use cookies. Read the Privacy and Cookie Policy

Что плохого в методе возврата ошибки, подобном применяемому в FORTRAN? Факториал не может быть отрицательным, поэтому я мог бы сказать что-то вроде: "Если функция factorial( ) обнаруживает ошибку, она возвращает отрицательное число. Значение отрицательного числа будет указывать на источник проблемы". Чем же плох такой метод? Ведь так было всегда.

_________________

291 стр. Глава 25. Обработка ошибок и исключения

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

Во-вторых, в целочисленной переменной не передашь много информации. Можно, конечно, обозначить ситуацию "аргумент отрицательный" как -1, ситуацию "аргумент слишком большой" как -2 и т.д. Но если аргумент слишком большой, я хотел бы знать, какой именно, поскольку это поможет мне найти источник проблемы. Однако в целочисленной переменной такую информацию не сохранишь.

В-третьих, проверка возвращаемого значения вовсе не обязательна. Чтобы понять, что я имею в виду, представьте себе, что кто-то написал функцию factorial( ), которая послушно проверяет, находится ли её аргумент в допустимых границах. Однако, если код, вызвавший эту функцию, не будет проверять возвращаемое значение, это не приведёт ни к чему хорошему. Конечно, я мог бы ввести в функцию всякие страшные угрозы наподобие "Вы обязательно должны проверить сообщения об ошибках, иначе...", но, думаю, не стоит объяснять, что язык не может никого ни к чему принудить.

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

    errRtn = someFunc( ) ;

    if ( errRtn )

    {

        errorOut( "Ошибка при вызове someFn( )" ) ;

        return MY_ERROR_1

    }

    errRtn = someOtherFunc( ) ;

    if ( errRtn )

    {

        errorOut( "Ошибка при вызове someOtherFn( )" ) ;

        return MY_ERROR_1

    }

Такой механизм имеет ряд недостатков.

■■■

■ Изобилует повторениями.

■ Заставляет программиста отслеживать множество разных ошибок и писать код для обработки всех возможных вариантов.

■ Смешивает код, отвечающий за обработку ошибок, с обычным кодом, что не добавляет ясности программе.

■■■

Эти недостатки кажутся безобидными в простом примере, но могут превратиться в большие проблемы, когда программа станет более сложной. В результате такой подход приводит к тому, что обработкой ошибок занимается 90% кода.

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

_________________

292 стр. Часть 5. Полезные особенности