Об’єктно-орієнтоване програмування (5) - книга, сторінка 29

12.1 Необхідність обробки винятків

Під час своєї роботи програма іноді стикається з позаштатними ситуаціями. Наприклад, викликаний метод деякого об'єкту може виявити у себе внутрішні проблеми (невірні значення полів, в результаті чого може відбутися, наприклад, розподіл на нуль) або знайти помилки в інших об'єктах або вхідних даних. Отже, необхідний деякий механізм виявлення і обробки позаштатних ситуацій (виключень) в програмі.

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

генерація інформації про виникнення помилкової ситуації, яка не може бути дозволена локально;

обробка помилок, виявлених в інших місцях.

Такий стиль обробка помилок краще багатьох традиційних методів. Розглянемо альтернативи. При виявленні проблеми, яка не може бути вирішена локально, програма може:

а) припинити виконання,

b) повернути спеціальне «помилкове» значення,

с) повернути якесь допустиме значення і залишити програму в

d) викликати функцію, призначену для обробки помилки.

Варіант а) - припинити виконання - це те, що відбувається за умовчанням, коли НЕ перехоплюється виняток. Для більшості помилок необхідно придумати щось краще. Бібліотечна функція, безумовно завершальна виконання, не може використовуватися в програмі, перша вимога до якої - надійність.

Варіант b) - повернути спеціальне «помилкове» значення - не завжди виконаємо, бо часто просто немає прийнятного помилкового значення (наприклад, при поверненні цілого будь-яке з них може бути прийнятно). Навіть коли такий підхід застосуємо, він часто незручний, тому що він змушує програміста кожен раз перевіряти результат на помилкове значення. Це легко може подвоїти розмір програми.

Варіант з) - повернути допустиме значення і залишити програму в ненормальному стані - має той недолік, що викликає функція може не помітити, що програма знаходиться в ненормальному стані. Наприклад, багато стандартні функції бібліотеки З встановлюють значення глобальної змінної errno для індикації помилки. Однак програми в більшості випадків не перевіряють цю змінну досить систематично, щоб уникнути подальших помилок. Більш того, використання глобальних змінних для запису інформації про помилки демонструє належного реагування при наявності паралельних процесів.

Варіант d) - викликати функцію, призначену для обробки помилки - покладає на викликану функцію вирішення проблеми одним з перерахованих вище способів.

Механізм обробки виключень надає альтернативу традиційним методам. Він дозволяє відокремити код обробки помилок від власного коду алгоритму, роблячи програму таким чином більш зрозумілою і більш «чистої». В результаті отримуємо більш регулярний спосіб обробки помилок, що спрощує взаємодію між окремо написаними фрагментами програми.

Загальні принципи обробки ситуацій в С ++, Яві і C #

Механізм обробки ситуацій дає спосіб передачі управління з точки виконання програми в розташовану вище з управління точку, в якій визначено обробник ситуації (exception handler). Головна ідея полягає в тому, що функція, що стикається з нерозв'язною проблемою, оголосить виняткову ситуацію, в надії на те, що викликала її (прямо чи опосередковано) функція може вирішити проблему. Оброблювач ситуації буде викликаний тільки в разі виконання опрератора-збудження-ситуації всередині так званого блоку-с-контролем або у функціях, викликаних з цього блоку. В С ++ і C # синтаксис збудження ситуації виглядає наступним чином:

У Яві синтаксис оператора збудження ситуації такий же за винятком того, що throw не може вживатися без вираження.

Оператор-збудження-ситуації в С ++ є вираженням деякого типу. У Яві і C # це завжди об'єкт деякого типу виключення, який повинен бути описаний явно. Оператор-збудження-ситуації іноді ще називають точкою виникнення (порушення) ситуації (throw-point). Про частини програми, в якій виповнився оператор-збудження-ситуації, кажуть, що в ній виникла ситуація (вона порушила ситуацію).

Розглянемо, яким чином в С ++ можна визначити і обробити помилки діапазону, що виникають в класі Vector.

class Range <>; // клас ситуацій

int operator [] (int i);

Об'єкти класу Range призначені для використання в якості винятків і порушувати останні наступним чином:

int Vector :: operator [] (int i)