Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
С++ / Джефф Элджер - C++ Библиотека программиста.pdf
Скачиваний:
111
Добавлен:
21.02.2016
Размер:
2.04 Mб
Скачать

69

Если во время конструирования объекта произойдет исключение, деструкторы будут вызваны для тех компонентов (базовых классов и переменных), конструкторы которых были выполнены к моменту возникновения исключения. Конструирование Ваr к этому моменту еще не завершено. Тем не менее, конструкторы базовых классов (Foo) и переменных (а и b) уже отработали, поэтому их деструкторы будут вызваны до передачи исключения обработчику. По тем же причинам будет вызван деструктор локальной переменной x. Деструктор у не вызывается, поскольку переменная еще не сконструирована. Деструктор Bar тоже не вызывается, поскольку конструирование объекта не завершилось к моменту инициирования исключения.

Предположим, конструктор b инициирует исключение. В этом случае вызываются деструкторы Foo и а, но не деструкторы b, Bar и у.

Одни и те же принципы действуют как для стековых, так и для динамических объектов. Если исключение возникает при конструировании динамического объекта, вызываются точно те же деструкторы, что и для стековых объектов.

Порядок вызова деструкторов

Гарантируется, что порядок вызова деструкторов будет обратным порядку вызова конструкторов. Это относится как к локальным переменным, так и к переменным и базовым классам объектов.

Нестандартная обработка исключений

Многие библиотеки и некоторые компиляторы обрабатывают исключения нестандартным образом. Большинство имитирует парадигму try/catch с помощью макросов, но не организует правильной раскрутки стека за счет вызова деструкторов конструированных объектов. Некоторые реализации ориентированы на конкретные типы компьютеров и операционных систем.

К сожалению, многие компиляторы претендуют на стандартную обработку исключений, но не во всем следуют каноническим правилам. На своем горьком опыте я узнал, что обработку исключений желательно тестировать, если вы делаете нечто хоть сколько-нибудь нестандартное (даже если оно должно быть стандартным). Если вы окажетесь в подобной ситуации, окажите услугу всем нам: наймите разработчика такого компилятора якобы для серьезного проекта и заставьте его писать и отлаживать код обработки исключений для его собственного компилятора в течение ближайших пяти лет. А еще лучше, заставьте его перенести в свой компилятор код, идеально работающий на другом компиляторе.

Если по какой-либо причине вам придется заниматься нестандартной обработкой исключений, больше всего проблем вызовет освобождение памяти от динамических объектов, которые были созданы до возникновения исключения и внезапно стали недоступными переменным. Именно для этой цели используется 99% обработки исключений в реальной жизни, да еще изредка требуется закрыть открытые файлы. Вы можете либо создать хитроумные структуры данных, которые перемещают новые динамические объекты на верх стека и, следовательно, сохраняют их доступность, либо воспользоваться методикой сборки мусора, описанной в последней части книги. Оба подхода выглядят в равной степени отталкивающе, так что выбирайте сами.

Условные обозначения

В этой книге я не использую ключевые слова throw и catch, а вставляю общие комментарии в тех местах, где может возникнуть исключение. Такой подход упрощает работу с программой, если ваш компилятор не поддерживает стандартную обработку исключений. Если вы увидите что-нибудь вроде следующего фрагмента и располагаете стандартной обработкой исключений, мысленно превратите комментарий в блок throw:

f()

{

if (pool->Allocate(size) == NULL) // исключение – нехватка памяти

}

Часть2

Косвенные

обращения

Когда указатель на самом деле не является указателем? Когда вы программируете на С++ и работаете с умными указателями. Одна из самых богатых (и самых недооцененных) концепций С++ — то, что объект может выполнять функции указателя. В этой части подробно рассматриваются различные способы, позволяющие это сделать, а заодно и примеры практического применения описанных идиом. Эта часть — не сборник рецептов, а скорее набор новых инструментов для вашей мастерской. Руки приложить все равно придется, но с хорошими инструментами работа пойдет гораздо легче.