Разработка кода, безопасного к возникновению исключений

· Объект, как минимум, должен оставаться destructible – последующий вызов деструктора данного объекта не должен приводить к сбою в приложении или неопределенному поведению

· При выбросе исключений не должно происходить утечек памяти и других ресурсов

· Объект, желательно, должен сохранить свою целостность, т.е, последующие вызовы методов объекта не должны приводить к сбоям или неопределенному поведению

· Желательно, объект должен вернуться в предсказуемое состояние, а еще лучше, в состояние, в котором он был до вызова метода, выбросившего исключение


24. Способы защиты от утечки ресурсов в случае возникновения исключительных ситуаций.

Если записать так:

try {

throw new std::exception("Ошибка");

} catch(...) {

...

}

то возникнет утечка ресурсов из-за того, что объект std::exception, созданный вдинамической памяти, не будет освобожден.

Поскольку в С+ отсутствует блок try…finally, его приходится эмулировать.

Object *p = new Object();

try{

...

}catch(...){

delete p;

throw;

}

deletep;

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


 

25. Генерирование исключительной ситуаций, создание пользовательских исключительных ситуаций.

Генерация (порождение) исключения происходит по ключевому слову throw,кото­рое употребляется либо с параметром, либо без него:

throw [ выражение ];

Тип выражения, стоящего после throw,определяет тип порождаемого исключения. При генерации исключения выполнение текущего блока прекращается, и происхо­дит поиск соответствующего обработчика и передача ему управления. Как прави­ло, исключение генерируется не непосредственно в try-блоке, а в функциях, прямо или косвенно в него вложенных.

Не всегда исключение, возникшее во внутреннем блоке, может быть сразу пра­вильно обработано. В этом случае используются вложенные контролируемые блоки, и исключение передается на более высокий уровень с помощью ключево­го слова throwбез параметров.

Также можно создавать собственные классы исключений, производные от класса Exception.

При создании собственных исключений рекомендуется завершать имя класса пользовательского исключения словом "Exception". Также рекомендуется реализовать три общих конструктора, как показано в следующем примере.

ПРИМЕР: Собственных пользовательских исключительных ситуаций

using namespace System;

 

public ref class EmployeeListNotFoundException : Exception

{

public:

EmployeeListNotFoundException()

{

}

EmployeeListNotFoundException(String^ message)

: Exception(message)

{

}

EmployeeListNotFoundException(String^ message, Exception^ inner)

: Exception(message, inner)

{

}

};

 


 

26. Понятие перегрузки методов, разрешение перегрузки.

Перегрузка методов— возможность использования одноимённых подпрограмм: процедур или функций в языках программирования.

Для того, чтобы иметь возможность использовать несколько вариантов подпрограммы с одним и тем же именем, но с разным числом аргументов или другими типами аргументов (то есть с разной сигнатурой) и вводится перегрузка подпрограмм. Такая перегрузка возможна в рамках процедурной парадигмы, без применения объектно-ориентированного программирования.

При трансляции происходит контроль одноимённых процедур и функций, чтобы они различались по сигнатуре, так как в этом случае транслятор может однозначно определить вызов нужной подпрограммы.

Чтобы исключить ошибку программиста давшему случайно имя подпрограмме, которое уже используется, вводится дополнительное требование написания ключевого слова. Так сделано, например в языке Delphi (ключевое слово overload).

Разрешением перегрузки функции называется процесс выбора той функции из множества перегруженных, которую следует вызвать. Этот процесс основывается на указанных при вызове аргументах.


27. Понятие перегрузки операторов.