Генерацию и перехват исключений не рекомендуется использовать в целях, отличных от обработки ошибок. Считается, что это может уменьшить ясность программы.
Считается также, что механизмы обработки исключением изначально создавались для обработки сравнительно редко проявляющихся ошибок и использовались чаще всего для завершения работы программы. В силу этого нет (пока нет) никакой гарантии относительно оптимальности, эффективности и надёжности этого механизма в качестве средства для обычного программного управления.
Вместе с тем, далеко не каждая исключительная ситуация должна вести к завершению программы. Например, при вычислении частного от деления двух случайных чисел, система управления исключением в случае возможного деления на нуль оказывается одним из основных средств управления программой.
Примерно такая же ситуация складывается и в нашем примере. Мы специально моделируем исключительные ситуации для оценки возможностей применения механизма перехвата.
Мы не будем всякий раз прерывать ход выполнения программы из-за того, что возникла какая-то странная ситуация. Если мы в силах восстановить нормальный ход выполнения программы - мы должны сделать это.
И если исключительная ситуация возникает в цикле - пусть её перехватчик остановит цикл. А вопросы эффективности и корректной работы со стеком - это вопросы к транслятору.
#include <iostream.h> #include <string.h> /* "Рабочее тело" одного из исключений. На его основе создаётся объект исключения. */ class MyException { public: int CopyKey; char *ExcMessage; // Конструктор умолчания. MyException(): ExcMessage("Стандартное сообщение от MyException...") { CopyKey = 0; } // Конструктор копирования. MyException(const MyException& MyExcKey) { cout << "Работает конструктор копии..." << endl; ExcMessage = strdup(MyExcKey.ExcMessage); CopyKey = 1; // Признак копии для деструктора. } // Деструктор освобождает динамическую память. ~MyException() { if (CopyKey && ExcMessage) delete(ExcMessage); } }; int MyFun() throw (int, char *); int Fun2() throw (int); void main() throw (MyException) { int RetMainVal; for (RetMainVal = 0; RetMainVal >= 0; ) { try { RetMainVal = MyFun(); cout << "RetMainVal == " << RetMainVal << endl; if (RetMainVal == 9) throw MyException(); /* Вызов конструктора для создания безымянного объекта - представителя класса MyException в точке возбуждения исключения (с использованием выражения явного преобразования типа). После этого код, расположенный ниже точки генерации исключения уже не выполняется. */ cout << "Последний RetMainVal не был равен 9!" << " Иначе были бы мы здесь..." << endl; } // Место расположения перехватчиков исключений. catch (int ExcVal) { cout << "(int) ExcVal == " << ExcVal << endl; } catch (char *ExcMessage) { cout << "(char *) ExcMessage " << ExcMessage << endl; } catch (MyException ExcObj) /*