Форум программистов, компьютерный форум CyberForum.ru

Try..catch..Throw - C++

Войти
Регистрация
Восстановить пароль
Другие темы раздела
C++ Оформление программы http://www.cyberforum.ru/cpp-beginners/thread330026.html
Как довести до ума программу на с++? Оформить, поменять цвет, шрифт, подписать???
C++ Есть класс A и класс B, класс B вложен в класс A и вложен в него, как классу B получить доступ к переменным класса A просто по имени? На самом деле ничё фантастического я не прошу, ведь: template <class T> class matrix { friend class diagonal; //Вложенный класс public: class diagonal; http://www.cyberforum.ru/cpp-beginners/thread330024.html
C++ Создать класс время с данными-членами часы, минуты, секунды
отучилась на программиста уже год, но пока что как-то тяжко с заданиями, тем более с классами, не успели пройти их... помогите пожалуйста решить Создать класс время с данными-членами часы, минуты, секунды. Перегрузить операторы сложения, вычитания(подсчет количества секунд между временем), ввода и вывода. Создать функции-члены сложения времени с заданным количеством секунд, вычитания из времени...
C++ Как послать своё сообщение другому приложению?
#define WM_MYMESSAGE 2000 void main() { HWND hWnd; hWnd = ::FindWindow(NULL,"MyApp"); ::SendMessage(hWnd,WM_MYMESSAGE,0,0); }
C++ Класс "Студент", реализовать динамический список "Группа студентов" http://www.cyberforum.ru/cpp-beginners/thread329994.html
реализовать динамический список " группа студентов". Узел: -группа -фамилия Функции списка: -добавление по алфавиту -удаление указанного -очистка списка -поиск студента -печать списка
C++ Связь указателей и одномерных массивов. Динамический одномерный массив Ребят помогите написать программу.В пятницу срочно надо сдать! Требования и общие указания к заданиям: • разработать класс для работы с одним или несколькими одномер-ными динамическими массивами, предусмотрев конструктор, деструктор, методы для ввода, вывода массива и в зависимости от варианта один или несколько методов для обработки массивов. По усмотрению пре-подавателя в класс можно... подробнее

Показать сообщение отдельно
ValeryLaptev
Эксперт С++
1035 / 814 / 48
Регистрация: 30.04.2011
Сообщений: 1,658
06.07.2011, 00:01     Try..catch..Throw
Правильные книжки надо читать...
Вот тебе из моей:

Принципы обработки исключений
В С++ исключение — это объект. Хотя обычно говорят об исключительной ситуации в программе, такая точка зрения мало что дает, так как с ситуацией сделать ничего нельзя. Поэтому в С++ при возникновении исключительной ситуации программа должна генерировать объект-исключение. Собственно, сама генерация объекта-исключения и создает исключительную ситуацию. Такой подход очень удобен, так как с объектами, в отличие от ситуации, мы можем много чего делать. Например, объявлять как обычную переменную, передать его как параметр любым из возможных способов или возвратить в качестве результата. Можно объявлять массивы исключений или включать объекты-исключения в качестве полей в другие классы. В дальнейшем мы будем использовать термин «исключение», понимая под этим объект-исключение.

Общая схема обработки исключений такова: в одной части программы, где обнаружена аварийная ситуация, исключение порождается; другая часть программы контролирует возникновение исключения, ловит и обрабатывает его. В С++ есть три зарезервированных слова: try (контролировать), catch (ловить), throw (порождать), — которые и используются для организации процесса обработки исключений.

Генерация исключений
Генерируется исключение оператором throw [1-15.1], который имеет следующий синтаксис
throw выражение_генерации_исключения;
Фраза «выражение_генерации_исключения» на практике означает либо константу, либо переменную некоторого типа. Тип объекта-исключения может быть любым, как встроенным, так и определяемым программистом. Например,
C++
1
2
3
4
throw 7;
throw "Ошибка: деление на ноль!";
throw Message[i];
throw M_PI;
В первом случае объект-исключение — это целая константа, которая может быть условным номером-кодом ошибки. В общем случае этот код ошибки может вычисляться, например
C++
1
throw 3*v-i;
Выражение, конечно, может быть не только целочисленным.
Второй вариант — это символьная константа, которая фактически является сообщением об ошибке. Если все сообщения об ошибках записаны в массиве, например,
C++
1
string Message[326];
то в третьем варианте объект-исключение тоже представляет собой строку — сообщение об ошибке. В последнем примере в качестве объекта используется дробная константа — число.
Программист может и сам определить свой собственный тип объекта-исключения, объявив новый класс, например
C++
1
2
3
4
class NegativeArgument{};
NegativeArgument exeption;
if (x>0) double t = x/sqrt(x);
else throw exeption;
Пустые классы неожиданно пригодились! Однако объявлять переменную совсем не обязательно, можно обойтись и без этого, например
C++
1
throw NegativeArgument();
Здесь в качестве «выражения генерации исключения» мы использовали явный вызов конструктора без аргументов, и это наиболее часто используемая форма генерации исключения.
Объект-исключение может быть и динамическим, например,
C++
1
throw new NegativeArgument();
Однако в этом случае возникает вопрос об уничтожении объекта-исключения и возврате памяти — неизвестно, в каком месте программы это можно сделать. Лучше не создавать себе проблем и не использовать указатели в качестве параметров catch-блоков.

Перехват и обработка исключений
Сгенерировать исключение — это только полдела. Исключение надо перехватить и обработать. Проверка возникновения исключения делается с помощью оператора try, с которым неразрывно связаны одна или несколько секций-ловушек catch. Оператор try объявляет в любом месте программы контролируемый блок, который имеет следующий вид
C++
1
try { /* контролируемый блок */ }
Контролируемый блок, помимо функции контроля, обладает функциями обычного блока: все переменные, объявленные внутри него, являются локальными в этом блоке и не видны вне его.
После try-блока обязательно прописывается один или несколько catch-блоков, которые обычно называют обработчиками исключений. Форма записи секции-ловушки следующая:
C++
1
catch (спецификация_исключения) { /* блок обработки */}
«Спецификация_исключения» может иметь следующие три формы:
(тип имя)
(тип)
(…)
Тип должен быть одним из допустимых типов исключений — либо встроенный, либо определенный программистом . Первый вариант спецификации означает, что объект-исключение передается в блок обработки, чтобы там его как-то использовать, например, для вывода информации в сообщении об ошибке.

ВНИМАНИЕ
При выполнении оператора throw создается временный объект-исключение [1 15.1/3], который и передается в секцию-ловушку.

При этом объект-исключение может передаваться в секцию-ловушку любым способом: по значению, по ссылке или по указателю, например
C++
1
2
3
4
catch (TException e)            // по значению
catch (TException& e)           // по ссылке
catch (const TException& e)     // по константной ссылке
catch (TException *e)           // по по указателю
Однако в отличие от параметров функций, никаких преобразований по умолчанию не производится . Это означает, что если в программе написан заголовок обработчика,
catch (double e) // по значению
то попадают в эту секцию только те исключения, тип выражения исключений которых совпадает с double. Оператор
C++
1
throw 1
генерирует исключение целого типа, поэтому будет обрабатываться секцией-ловушкой с заголовком, в которой прописан целый тип исключения, например
C++
1
catch (int e)           // по значению
или
C++
1
catch (int)             // без передачи информации в секцию-ловушку
Это легко проверить, выполнив следующую простую тестирующую программу:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
int main()
{   try { throw 1;                          // генерация исключения
        }
    catch(unsigned int)
        { cout << "unsigned integer" << endl;
        }
    catch(int)                              // перехватывается здесь
        { cout << "integer" << endl;
        }
    catch(double)
        { cout << "double" << endl;
        }
    return 0;
}
На экране появится слово integer, так как константа 1 по умолчанию имеет тип int.
Первые две формы из приведенных выше спецификаций исключения предназначены для обработки конкретного типа исключений. Если же на месте спецификации исключения написано многоточие (как в функциях с переменным числом параметров), то такой обработчик перехватывает все исключения.

Работа конструкции try-catch напоминает работу оператора switch. Секции-ловушки похожи на альтернативы case, а catch-блок с многоточием соответствует альтернативе default оператора-переключателя. Если в try-блоке возникает исключение, то начинается сравнение типа сгенерированного исключения и типов параметров в секциях-ловушках. Выполняется тот catch-блок, тип параметра которого совпал с типом исключения. Если такого типа не найдено, но есть catch с многоточием, то выполняется его блок. Если же такого блока в текущем списке обработчиков не обнаруживается, то ищется другой список обработчиков в вызывающей функции. Этот поиск продолжается вплоть до функции main(). Если же и там не обнаружится нужного catch-блока, то вызывается стандартная функция завершения terminate() [1-15.5.1], которая вызывает функцию abort().

Таким образом, очень важен порядок записи секций-ловушек после контролируемого блока. Если в качестве первого обработчика после try-блока задан catch-блок с параметром-многоточием, то такой обработчик будет обрабатывать все возникающие исключения — до остальных секций-ловушек дело просто не дойдет. Поэтому усвойте следующее простое правило: всегда задавать catch-блок с параметром-многоточием последним. Секция-ловушка с многоточием — это крайняя мера: если уж мы в нее попали, то в программе произошло что-то совсем не предусмотренное. Поэтому в такой секции обычно выводят сообщение о непредвиденном исключении и завершают работу программы.
Выход из секции-ловушки выполняется одним из следующих способов:
1. выполнились все операторы обработчика — происходит неявный переход к оператору, расположенному после конструкции try-catch;
2. в обработчике выполняется оператор goto ; разрешается выполнять переход на любой оператор вне конструкции try-catch; внутрь контролируемого блока и в другую секцию-ловушку переход запрещен;
3. в обработчике выполняется оператор return; происходит нормальный выход из функции;
4. в секции ловушке выполняется оператор throw;
5. в обработчике генерируется другое исключение.
Рассмотрим подробнее два последние способа выхода. Оператор throw без выражения генерации исключения генерирует повторное исключение того же типа. Такая форма оператора допустима только внутри секции-ловушки.

ПРИМЕЧАНИЕ
Выполнение этого оператора вне секции-ловушки приведет к немедленному аварийному завершению программы [1-15.1/8].

Однако это не приводит к рекурсивному входу в тот же обработчик — ищется другой обработчик выше по иерархии вложенности. Аналогично, при генерации в секции-ловушке исключения другого типа ищется его обработчик выше по иерархии вложенности. Если нужного catch-блока не обнаруживается, то программа аварийно завершается. Таким образом, мы имеем возможность «распределить» обработку исключения по разным частям программы.
Выход из обработчика по исключению может привести к выходу из функции. Очень важно, что стандарт [1-15.2/1] гарантирует в этом случае вызов деструкторов для уничтожения локальных объектов. Этот процесс уничтожения локальных объектов при выходе по исключению называется «раскруткой» (unwinding) стека. Нужно подчеркнуть, что раскрутка стека выполняется только для локальных объектов — для динамических объектов, созданных операцией new, деструкторы автоматически не вызываются. Маленький пример продемонстрирует эту ситуацию:
C++
1
2
3
4
5
6
7
8
9
10
void f1(void)
{ //…
  MyObject t;
  throw MyException();
}
void f2(void)
{ //…
  MyObject t = new MyObject();
  throw MyException();
}
Генерация исключения в функции f1() приведет к вызову деструктора для уничтожения локального объекта t. При генерации исключения в функции f2() деструктор класса MyObject не вызывается, так как объект создан в динамической памяти. Более того, уничтожается локальный указатель, и это приводит к утечке памяти. Обычно эта проблема решается с помощью интеллектуальных указателей [20, 21, 24, 25, 28].

ПРИМЕЧАНИЕ
В стандартной библиотеке STL реализован один из видов интеллектуальных указателей auto_ptr.

После выполнения операторов catch-блока при отсутствии явных операторов перехода или оператора throw выполняются операторы, расположенные после всей конструкции try-catch. Если во время работы в try-блоке не обнаружено исключительной ситуации, то все catch-блоки пропускаются, и программа продолжает выполнение с первого оператора после всех catch.
Блоки try-catch могут быть вложенными, причем как в try-блок, так и в catch-блок:
C++
1
2
3
4
5
6
7
8
9
10
try {   // блок, который может инициировать исключения
    try {   //вложенный блок
    }
    catch(){   }
}
catch (исключение) {    // обработка исключения
    try {   //вложенный блок
    }
    catch(){   }
}
Необходимо отметить, что исключение может быть сгенерировано в одном месте программы, а обработано совершенно в другом.
 
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru