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

Обработка исключительных ситуации - C++

Восстановить пароль Регистрация
 
Рейтинг: Рейтинг темы: голосов - 42, средняя оценка - 4.67
REALIST07
Автор FAQ
Автор FAQ
 Аватар для REALIST07
174 / 174 / 13
Регистрация: 11.06.2010
Сообщений: 932
04.06.2011, 21:02     Обработка исключительных ситуации #1
Постройте таблицу значений функции y=f(x) для [a, b] с шагом h. Если в некоторой точке x функция не определена, то выведите на экран сообщение об этом. Замечание. При решении данной задачи использовать вспомогательный метод f(x), реализующий заданную функцию, а также проводить обработку возможных исключений.
Если можно объясните как обработку сделать!Примерно знаю,но не въезжаю
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
OstapBender
 Аватар для OstapBender
581 / 519 / 35
Регистрация: 22.03.2011
Сообщений: 1,585
04.06.2011, 21:25     Обработка исключительных ситуации #2
банально сделай обработку деления на 0
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
double f(double x) {
 
if (что-то) throw std::string("Division by zero");
}
 
мейн:
try {
 
y=f(x);
 
} catch(std::string o) {
std::cout << o << '\n'; 
}
marina2
Рожденная для битвы
 Аватар для marina2
268 / 48 / 4
Регистрация: 08.11.2009
Сообщений: 1,016
04.06.2011, 21:31     Обработка исключительных ситуации #3
oop_labs.zip
Вот посмотри последнюю лабораторную. Давольно просто описано
REALIST07
Автор FAQ
Автор FAQ
 Аватар для REALIST07
174 / 174 / 13
Регистрация: 11.06.2010
Сообщений: 932
05.06.2011, 12:06  [ТС]     Обработка исключительных ситуации #4
Цитата Сообщение от OstapBender Посмотреть сообщение
catch(std::string o)
вот это не понимаю а так я понял примерно
ValeryLaptev
Эксперт C++
1005 / 784 / 46
Регистрация: 30.04.2011
Сообщений: 1,595
05.06.2011, 12:17     Обработка исключительных ситуации #5
Цитата Сообщение от REALIST07 Посмотреть сообщение
вот это не понимаю а так я понял примерно
Дык читайте первоисточники!
Из моей книжки:

Глава 7. Исключения
При выполнении любой программы бывают аварийные ситуации, вызванные самыми разнообразными причинами. Если мы делаем программу «для себя», то встроить в нее механизм обработки некоторых ошибок с выдачей соответствующих сообщений труда не представляет. Но в профессиональном программировании программы пишутся не для себя, а для других, поэтому такой метод обработки ошибок неприемлем.
При реализации класса строк (см. листинг 4.2) мы столкнулись как раз с такой ситуацией — одна из операций индексирования при неправильном параметре возвращала нулевой байт. Такое решение допустимо только для строк, так как в любой кодировке символ с нулевым кодом, как правило, входит в подмножество специальных символов. Для числовых массивов, очевидно, это решение не подходит — отсутствует специальное значение. Поэтому лучше просто не выполнять операцию, а сообщить о неверном параметре программе-клиенту.
Аналогичные проблемы возникают при реализации конструкторов. В классе TString (см. листинги 4.3–4.7) любой конструктор создавал пустую строку, если получал неправильные параметры. Для строк это решение можно было реализовать, так как в классе TString определено поле-массив фиксированного размера. Однако создать «умный» массив, если неправильно задана длина, нельзя, поскольку память выделяется динамически. Поэтому конструктор «умного» массива (см. листинги 5.2–5.4) завершался аварийно. В профессиональном программировании такое поведение программы совершенно неприемлемо — об аварии требуется сообщить программе-клиенту.
В обычной функции-методе для этих целей можно использовать либо дополнительный параметр, либо возвращаемое значение. Однако перегруженная операция не может иметь лишних параметров, поэтому должна в таких случаях возвращать некоторое «аварийное» значение. У конструктора же, как и у перегружаемых операций, в отличие от обычных функций, нет и такой возможности.
Таким образом, необходим языковый механизм, с помощью которого методы и конструкторы класса могли бы сообщать программе-клиенту об аварийной ситуации. В стандарт С++ для этих целей включен механизм обработки исключений (см. п. 15 в [1]).
Принципы обработки исключений
В С++ исключение — это объект. Хотя обычно говорят об исключительной ситуации в программе, такая точка зрения мало что дает, так как с ситуацией сделать ничего нельзя. Поэтому в С++ при возникновении исключительной ситуации программа должна генерировать объект-исключение. Собственно, сама генерация объекта-исключения и создает исключительную ситуацию. Такой подход очень удобен, так как с объектами, в отличие от ситуаций, мы можем много чего делать. Например, объект-исключение можно объявить как обычную переменную, передать его как параметр любым из возможных способов или возвратить в качестве результата. Можно объявлять массивы исключений или включать объекты-исключения в качестве полей в другие классы. В дальнейшем мы будем использовать термин «исключение», понимая под этим объект-исключение.
Общая схема обработки исключений такова: в одной части программы, где обнаружена аварийная ситуация, исключение порождается; другая часть программы контролирует возникновение исключения, перехватывает и обрабатывает его. В С++ есть три зарезервированных слова: try (контролировать), catch (перехватывать), throw (порождать), — которые и используются для организации процесса обработки исключений.

Генерация исключений
Генерируется исключение оператором throw (см. п. 15.1 в [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 создается временный объект-исключение, который и передается в секцию-ловушку (см. п.п. 15.1/3 в [1]).

При этом объект-исключение может передаваться в секцию-ловушку любым способом: по значению, по ссылке или по указателю, например:
C++
1
2
3
4
catch (TException e)             // по значению
catch (TException& e)            // по ссылке
catch (const TException& e)      // по константной ссылке
catch (TException *e)            // по по указателю
Однако в отличие от параметров функций, никаких преобразований типов по умолчанию не производится . Это означает, что если в программе написан следующий заголовок обработчика, то попадают в соответствующую ловушку только те исключения, тип которых совпадает с double:
C++
1
catch (double e)                 // по значению
Еще пример:
C++
1
throw 1
Этот оператор генерирует исключение целого типа, поэтому будет обрабатываться секцией-ловушкой с заголовком, в котором прописан целый тип исключения, например, одним из следующих способов:
C++
1
2
catch (int e)                    // по значению
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() (см. п.п. 15.5.1 в [1]), которая вызывает функцию abort().

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

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

Однако это не приводит к рекурсивному входу в тот же обработчик — ищется другой обработчик выше по иерархии вложенности. Аналогично, при генерации в секции-ловушке исключения другого типа ищется его обработчик выше по иерархии вложенности. Если нужного блока catch не обнаруживается, то программа аварийно завершается. Таким образом, мы имеем возможность «распределить» обработку исключения по разным частям программы.

Выход из обработчика по исключению может привести к выходу из функции. Очень важно, что стандарт (см. п.п. 15.2/1 в [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(...){    }
}
Необходимо отметить, что исключение может быть сгенерировано в одном месте программы, а обработано совершенно в другом.
vahAAA
0 / 0 / 0
Регистрация: 29.09.2013
Сообщений: 15
28.12.2013, 14:24     Обработка исключительных ситуации #6
а можно скинуть варианты всех заданий? очень нужно (только задания)
Yandex
Объявления
28.12.2013, 14:24     Обработка исключительных ситуации
Ответ Создать тему

Метки
исключение
Опции темы

Текущее время: 01:34. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru