Глава 25. ОБРАБОТКА ОШИБОК И ИСКЛЮЧЕНИЯ...290

ОГЛАВЛЕНИЕ

        В этой главе...

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

►Механизм исключительных ситуаций 293

►Так что же мы будем бросать? 295

Трудно с этим смириться, но факт остаётся фактом: иногда функции работают неправильно. Традиционно вызывающей программе сообщается об ошибке посредством возвращаемого функцией значения. Однако язык С++ предоставляет новый, улучшенный механизм выявления и обработки ошибок с помощью исключительных ситуаций, или просто исключений ( exceptions ). Исключение — это отступление от общего правила, т.е. случай, когда то или иное правило либо принцип неприменимы. Можно дать и такое определение: исключение — это неожиданное ( и, надо полагать, нежелательное ) состояние, которое возникает во время выполнения программы.

Механизм исключительных ситуаций базируется на ключевых словах try ( попытаться, пробовать, попытка [trai] [трай] ), throw ( бросить, бросание, бросок —   [θrou] — [сроу] ) и catch (  поймать, схватить, ловить [kætʃ] [кэчь] ). В общих чертах этот механизм работает так: функция пытается ( пробует — try ) выполнить фрагмент кода. Если в коде содержится ошибка, функция бросает ( генерирует — throw ) сообщение об ошибке, которое должна поймать ( перехватить — catch ) вызывающая функция. Это продемонстрировано в приведённой ниже программе.

    //

    /* FactorialException — демонстрация исключений */

    /*                  при использовании факториала */

    //

    #include <cstdio>

    #include <cstdlib>

    #include <iostream>

    #include <string>

    using namespace std ;

    /* factorial — вычисление факториала */

    int factorial( int n )

    {

        /* Функция не обрабатывает отрицательные  значения аргумента */

        if ( n < 0 )

        {

            throw string( "Аргумент отрицателен" ) ;

        }

        /* Вычисляем факториал */

        int accum = 1 ;

        while ( n > 0 )

        {

            accum *= n ;

_________________

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

            n-- ;

        }

        return accum ;

    }

    int main( int nNumberofArgs , char* pszArgs[ ] )

    {

            /* печать кириллицы, если Вы не установите программки gccrus.exe и g++rus.exe */

            setlocale ( LC_ALL , ".1251" ) ;

        try

        {

            /* Здесь всё в порядке */

            cout << "3! = " << factorial( 3 ) << endl ;

            /* Здесь генерируется исключение */

            cout << "-1!= " << factorial( -1 ) << endl ;

            /* Этот код так и  остаётся не выполнен */

            cout << "Factorial of 5 is " << factorial( 5 )

                  << endl ;

        }

        /* Обработка исключения */

        catch( string error )

        {

            cout << "Ошибка: " << error << endl ;

        }

        catch ( ... )

        {

            cout << "Неизвестное исключение" << endl ;

        }

        /* Пауза для того, чтобы посмотреть на результат работы программы */

        system( "PAUSE" ) ; return 0 ;

    }

Функция main( ) начинается с блока, выделенного ключевым словом try. В этом блоке выполнение кода ничем не отличается от выполнения вне блока. В данном случае main( ) пытается вычислить факториал отрицательного числа. Однако функцию factorial( ) не так легко одурачить, поскольку она достаточно умно написана и обнаруживает, что запрос некорректен. При этом она генерирует сообщение об ошибке с помощью ключевого слова throw. Управление передаётся фрагменту, находящемуся сразу за закрывающей фигурной скобкой блока try и отвечающему за перехват сообщения об ошибке. Следующий за ошибочным вызов функции factorial так и не выполняется.