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

    void Run() throw(Error) 
    { 
      throw "An unknown exception object"; 
    }

    Когда вы скомпилируете и запустите программу, обработчик непредвиденных 
ситуаций trapper() будет вызываться для каждой исключительной ситуации, 
возбуждаемой функцией Run(). Это происходит потому, что не существует 
оператора catch для объектов исключительных ситуаций типа const char* или 
char*. Функция trapperO, тем не менее, транслирует нераспознанные объекты 
исключительных ситуаций, посылая объект известного типа, в данном случае, 
Error. Новая возбужденная исключительная ситуация продолжает выполнение 
программы в операторе catch внутри функции main(), который обрабатывает 
транслированную исключительную ситуацию. 
    В конце концов, в программе максимальное число ошибок будет превышено, и 
объект класса МахЕггог будет послан конструктором Error. В результате 
вызовется обработчик завершения программы путем обращения к библиотечной 
функции exit()
. 
    Исключительные ситуации и локальные объекты 

    С помощью специальной опции компилятора локальные объекты, оставшиеся в 
стеке, автоматически уничтожаются возбуждением исключительной ситуации, т.е. 
вызываются деструкторы этих объектов. Для разрешения автоматического 
уничтожения задайте опцию -xd для автономного компилятора. Или же из 
интегрированной среды выберите Options\Project..., откройте пункт C++ Options 
и выберите подпункт Exception handling\RTTI. (RTTI — Runtime Type Information, 
информация о типах времени исполнения). Убедитесь, что установлены пункты 
Enable exceptions и Enable destructor cleanup. 
    
    ЗАМЕЧАНИЕ

    Вы обязательно должны устанваливать автоматическую очистку деструкторами
для ObjectWindows-программ (OWL).

    В целом автоматическое уничтожение необходимо для функций, которые 

    •  создают локальные объекты, 
    •  возбуждают исключительные ситуации после создания объектов. 

    Простой пример демонстрирует, почему эти два пункта важны для вас. 
Следующая функция может оставить объект класса AnyClass в стеке: 

    int AnyFunction() 
    { 
      AnyClass object(123); 
       // ... 
       if (condition) throw Error(); 
       return object.Value(); 
    )

    Функция создает в стеке объект класса AnyClass. Если события развиваются 
нормально, при завершении функции вызовется деструктор объекта. Однако, если 
функция завершится исключительной ситуацией, деструктор объекта не вызовется, 
что в некоторых случаях может привести к серьезным проблемам, например, если в 
программе не освобождается выделенная для объекта память. 
    Использование ключа -xd автономного компилятора или аналогичных установок 
в интегрированной среде гарантирует, что в подобных случаях деструктор для 
object будет вызван по завершению функции в результате возбуждения 
исключительной ситуации. Обычно такая установка желательна, однако ее 
использование gриводит к накладным расходам, их можно избежать, если в вашей 
программе нет локальных объектов в функциях, в которых возбуждаются 
исключительные ситуации. (Не забудьте, что вы обязаны в любом случае 
установить опцию автоматического уничтожения для программ, использующих OWL.) 


    Глава 15. Передовые средства C++     415 
