67365

Повторне генерування винятку

Лекция

Информатика, кибернетика и программирование

Для того, щоби повторно згенерувати винятки в його обробнику, необхідно використовувати throw-настанову без вказання типу винятку. У цьому випадку поточний виняток передається в зовнішню try/catch-послідовність. Найчастіше причиною для такого виконання настанови throw слугує прагнення мати доступ до одного винятку декільком обробникам.

Украинкский

2014-09-07

79.5 KB

0 чел.

Лекція № 25

Тема: Повторне генерування винятку

   Для того, щоби повторно згенерувати винятки в його обробнику, необхідно використовувати throw-настанову без вказання типу винятку. У цьому випадку поточний виняток передається в зовнішню try/catch-послідовність. Найчастіше причиною для такого виконання настанови throw слугує прагнення мати доступ до одного винятку декільком обробникам. Наприклад, перший обробник винятків повідомлятиме про один аспект винятку, а другий – про щось інше. Винятки можна повторно згенерувати тільки в catch-блоці (або в будь-якій функції, яка викли-

кається з цього блоку). При повторному генеруванні винятку сам виняток не перехоплюватиметься тією ж catch-настановою. Він пошириться на найближчу try/catch-послідовність.

    Повторне генерування винятку типу char * продемонстровано у наведенному нижче коді програми.

Приклад. Демонстрація механізму повторного генерування винятку типу char *

 

void Xhandler()

{

 try

{

 throw "Привіт";                 // Генерує винятки типу char *

}

catch(char *)

{     // Перехоплює винятки типу char *

 cout << "Перехоплення винятку у функції Xhandler" << endl;

 throw;                // Повторне генерування винятку типу char *,

                           // яке перехоплюватиметься поза функцією Xhandler.

}

}

void main()

{

cout << "Початок" << endl;

try

{

 Xhandler();

}

catch(char *)

{

 cout << "Перехоплення винятку у функції main()" << endl;

}

}

   Внаслідок виконання ця програма відображає на екрані такі результати:

Початок.

Перехоплення винятку у функції Xhandler.

Перехоплення винятку у функції main().

Кінець програми

Тема: Обробка винятків, згенерованих оператором new

   Як зазначалося вище, оператор new генерує винятки, якщо не вдається задовольнити запит на виділення області пам'яті. Там опис оброблення винятків такого типу було відкладено на потім. Якраз тепер настав час розглянути цю проблему детальніше.

   Спершу необхідно зазначити, що у цьому розділі описано поведінку оператора new відповідно до стандарту мови C++. Проте, дії, які здійснює система при неуспішному використанні оператора new, з моменту появи мови C++ змінювалися вже декілька разів. Спочатку оператор new повертав при невдачі значення NULL. Пізніше така поведінка була замінена генеруванням винятку, ім'я якого також мінялося кілька разів. Нарешті, було вирішено, що оператор new генеруватиме виняток за замовчуванням, але як альтернативний варіант він може повертати і нульовий показник. Отже, оператор new у різний час був реалізований різними способами. І хоча всі сучасні компілятори реалізують оператор new відповідно до стандарту мови C++, компілятори "поважнішого" віку можуть містити відхилення від нього.

   Згідно зі стандартом мови C++, у випадку неможливості задовольнити запит на виділення області пам'яті, потрібної операторові new, генерується виняток типу bad_alloc. Якщо Ваша програма не перехопить його, то вона буде завчасно завершена. Хоча така поведінка виправдана для коротких прикладів програм, в реальних додатках необхідно перехоплювати цей виняток і розумно обробляти його.

   Щоб отримати доступ до винятку типу bad_alloc, потрібно залучити до програми заголовок <new>.

   Розглянемо приклад використання оператора new, поміщеного в try/catch-блок для вистежування невдалих результатів запиту на виділення області пам'яті.

Приклад. Демонстрація механізму оброблення винятків, згенерованих оператором new

int main()

{

int *p;

try

{

 p = new int[32]; // Запит на виділення області пам'яті

 // для 32-елементного int-масиву

}

 catch(bad_alloc ха)

{

 cout << "Пам'ять не виділена" << endl;

 return 1;

}

for(int i=0; i<32; i++) p[i] = i;

for(int i=0; i<32; i++) cout << p[i] << " ";

delete [] p; // Звільнення пам'яті

}

   Під час невдалого виконання оператора new виняток у цьому коді програми буде перехоплено catch-настановою. Цей самий підхід можна використовувати для вистежування будь-яких помилок, взаємопов'язаних з використанням оператора new: достатньо помістити кожну new-настанову в try-блок.

  Альтернативна форма оператора new – nothrow.

   Стандарт мови C++ при невдалій спробі виділення області пам'яті оператором new замість генерування винятку також може повертати значення NULL. Ця форма використання оператора

new особливо корисна у процесі компілювання старих програм із застосуванням сучасного С++-компілятора. Вона також корисна при заміні викликів функції malloc() оператором new. Це звичайна практика у процесі перекладу С-коду програми на мову програмування C++. Отже, формат оператора new має такий вигляд:

p_var = new(nothrow) тип;

   У цьому записі елемент p_var – це покажчик на змінну типу тип. Цей nothrow- формат оператора new працює подібно до оригінальної версії оператора new, яка використовувалася кілька років тому. Оскільки оператор new(nothrow) повертає при невдачі значення NULL, його можна "упровадити" в старий код програми, не вдаючись до оброблення винятків. Проте в нових програмах, написаних мовою C++, все ж таки краще мати справу з генеруванням винятків.

   У наведеному нижче прикладі показано, як використовується альтернативний варіант new(nothrow). Неважко здогадатися, що нижче наведено можливий варіант попереднього коду програми.

Приклад. Демонстрація механізму використання nothrow як старої версії оператора new

int main()

{

int *p;

p = new(nothrow) int[32]; // Використання nothrow-версії

if(!p)

{

 cout << "Пам'ять не виділена" << endl;

 return 1;

}

for(int i=0; i<32; i++) p[i] = i;

for(int i=0; i<32; i++) cout << p[i] << " ";

delete [] p; // Звільнення пам'яті

}

   У цьому коді програми під час використання throw-версії після кожного запиту на виділення області пам'яті необхідно перевіряти значення покажчика, що повертається оператором new.


 

А также другие работы, которые могут Вас заинтересовать

26308. Причины великих географических открытий 16.73 KB
  Причины великих географических открытий Особое место в процессе зарождения рыночных отношений занимали Великие географические открытия конец XVXVII век благодаря которым удалось установить новые торговые пути вовлечь в мировой хозяйственный оборот огромные ресурсы других стран и континентов. главными из которых были открытие Америки и морского пути в Индию вокруг Африки. В XIIIXV веках все кратчайшие торговые пути туда были перекрыты: турки захватили Балканы и Ближний Восток арабы Северную Африку Русь находилась под гнетом монгол...
26309. Важнейшие открытия XV – середины XVII в 19.21 KB
  В 14821486 годах Диогу Кан Cao пересек экватор открыл устье реки Конго и прошел вдоль побережья Африки до мыса Кросс. В 14871488 годах Бартоломеу Диаш совершил новое беспримерное плавание на юг. В 15921504 годах он совершил четыре плавания через Атлантический океан открыл Большие Антильские и часть Малых Антильских островов побережье Южной и Центральной Америки. В 14971498 годах Васко да Гама на четырех судах обогнул Африку и с помощью арабских кормчих достиг настоящей Индии.
26310. Последствия Великих географических открытий 17.9 KB
  Важнейшим следствием открытия и колонизации новых земель явилась революция цен которая дала мощный импульс первоначальному накоплениюкапитала в Европе и ускорила формирование капиталистического уклада в хозяйстве. цен на сельскохозяйственные и промышленные товары. цены были в основном стабильными то за 70 лет – с 30х годов XVI в. Такое движение цен современники связывали либо с большим притоком драгоценных металлов в Европу либо с их утечкой.
26311. Колониальные захваты Испании и Португалии в XVI – XVII в 26.59 KB
  Плантационное рабство получило наибольшее развитие в Бразилии где выращивались сахарный тростник рис кукуруза и табак а также в ВестИндии Венесуэле и Новой Гранаде. С совершенно иными условиями встретились португальцы в Индии. Но португальцы сумели воспользоваться одним важным преимуществом: они обладали более сильным флотом чем мелкие феодальные владетели в Индии Индонезии ИндоКитае. Пиратскими методами захватывая грабя истребляя экипажи кораблей мусульманских купцов державших в своих руках морскую торговлю Индии до прихода...
26312. Реформация в Германии. М.Лютер 42.72 KB
  Религиозное настроение Германии проявлялось в переводах Библии и в развитии церковной песни еще до Лютера; своим знаменитым переводом и своей богослужебной лирикой он только затмил более ранние проблески стремления читать Священное Писание и молиться на родном языке. Годы непосредственно предшествовавшие выступлению Лютера и избранию на престол Карла V были временем большого возбуждения выразившегося в развитии литературы памфлетов и летучих листков. когда Лютер выступил со своими тезисами против индульгенций. после того как и Лютер и...
26313. Крестьянская война в Германии. Т.Мюнцер 40.51 KB
  Крестьянская война в Германии: Обострение классовой борьбы народных масс в деятельность союза Башмак С наступлением феодальной реакции нарастала борьба крестьян. характерно значительно более тесное сближение крестьянской массы с городскими низами чем в предшествовавший период. Усиление же крестьянскоплебейского лагеря не могло не оказать влияния на радикальные элементы в бюргерстве и на известный подъём бюргерской оппозиции вообще. Такое крестьянское общество было раскрыто в 1502 г.
26314. Реформация в Швейцарии. У.Цвингли и Ж.Кальвин 34.59 KB
  Начало же этому было положено в Цюрихе где в 1518 году священником кафедрального собора был избран известный проповедник Ульрих Цвингли. Даже изгнание Цвингли торговца индульгенциями монаха Самсона удостоилась не осуждения а похвалы представителя местного епископа. Так продолжалось до 1522 года когда Цвингли сам пошел на обострение ситуации. Однако и этот вызов не вызвал ожидаемых мер со стороны римского священноначалия напротив папский легат передал Цвингли письмо в котором ему сулились огромные блага если бы он стал поддерживать...
26315. Реформация и религиозные (гражданские) войны во Франции 29.06 KB
  Широко стали распространяться идеи Кальвина во Франции при короле Генрихе II. Именно при Генрихе II кальвинизм во Франции достиг наибольшего распространения. Ослабление королевской власти при сыновьях Генриха II благоприятствовало политическим притязаниям феодальной аристократии и борьба за религиозную свободу слилась с борьбой за власть. Своего короля Генриха Наваррского гугеноты воспринимали как конституционного государя.
26316. Реформация в Англии 14.33 KB
  Реформация в Англии Англия страна известная своими реформаторскими тенденциями. Однако решающую роль в Реформации в Англии предстояло сыграть другому человеку. Реформацию в Англии можно в полном смысле назвать Реформацией сверху так как во главе её стал английский король Генрих VIII. Реформация в Англии при Генрихе VIII Первоначально Генрих был противником Реформации даже написал книги против Лютера В защиту семи таинств 1521 в основе которой были не аргументы а брань в адрес виттенбергского реформатора.