Тема: Исключительные ситуации
ПЛАН ЗАНЯТИЯ №30
Дисциплина: ОП.05 Основы программирования
Преподаватель: Машарова Р.В.
Курс: 3
Группа: 1 ПКС-20
Специальность: Программирование в компьютерных системах
Дата: 14.12.2022
Время проведения: 09.50-11.20, 2 пара
Тема: Исключительные ситуации
Цель занятия:
Дидактическая: познакомиться с понятием исключительной ситуации
Развивающая: развивать логическое и критическое мышление, умение обобщать и синтезировать знания
Вид занятия лекция
Литература:
1. Павловская Т.А. С/С++. Программирование на языке высокого уровня. 2 изд. – Спб. Питер, 2011. – 464 с.: ил.
2. Павловская Т. А., Щупак Ю. А. C/C++. Структурное и объектно-ориентированное программирование. Практикум. – Спб. Питер, 2010. – 352 с.
3. Семакин И.Г., Шестаков А.П. Основы алгоритмизации и программирования: учебник для студентов учреждений сред.проф. образования – М.: издательский центр «Академия», 2013 – 400 с.
4. Семакин И.Г., Шестаков А.П. Основы алгоритмизации и программирования. Практикум: учебник для студентов учреждений сред.проф. образования – М.: издательский центр «Академия», 2013 – 400 с.
Лекция №59
Тема: Исключительные ситуации
1. Исключительные ситуации
Настоящий раздел посвящен обработке ошибок в программе с использованием исключений. Однако прежде, чем перейти непосредственно к изучению механизма работы с исключениями, рассмотрим такой пример. Пусть имеется класс, представляющий список вещественных чисел. В этом случае мы могли бы реализовать функцию чтения элемента по индексу, например, так, как показано ниже.
classСDblList
{structlist{
doubledata; list* link;} *m_head; public:
doubleGet(intindex) { list *p = m_head;
while (index) { p = p->link; index--; } return p->data;}…};
Полагаем, даже начинающий программист заметит, что приведенное решение далеко не самое лучшее, так как задание неверного индекса приведет к ошибке в программе из-за обращения по нулевому указателю. Чтобы исключить такую возможность мы могли бы вставить дополнительные проверки:
doubleGet(intindex) { list *p = m_head;
while (p &&index) { p = p->link; index--; } if (p) return p->data;}
Однако в этом случае при ошибочном индексе значение, возвращаемое функцией, не задается. Таким образом, мы оказываемся в ситуации, когда хорошо было бы вернуть некоторое значение и сообщить вызывающей функции об ошибочном индексе. Конечно, можно поступить и кардинальным образом:
doubleGet(intindex) { list *p = m_head;
while (p &&index) { p = p->link; index--; } if (p) return p->data;
elseabort();}
Однако пользователя вряд ли устроит, если на каждое неверное действие программа будет аварийно завершаться. Рассмотрим другой вариант - проигнорировать ошибку и вернуть некоторое допустимое значение:
doubleGet(intindex) { list *p = m_head;
while (p &&index) { p = p->link; index--; } if (p) return p->data;elsereturn 0;}
В этом случае функция будет работать всегда, и если предопределенное значение (в нашем случае – 0) не может содержаться в списке, то это не такой уж и плохой способ сообщить об ошибке. В частности, для указателей таким специальным значением является NULL, для индексов в массиве можно зарезервировать -1 и т.д. Однако если такого значения или диапазона значений зарезервировать не удается, то вызывающая функция никогда не узнает о том, произошла ли ошибка или возвращено требуемое значение. Один из традиционных способов сообщить об ошибке – возвращать признак успешности выполнения функции (или код ошибки):
boolGet(intindex, double&result) { list *p = m_head;
while (p &&index) { p = p->link; index--; } if (p) result = p->data;
return (p != NULL);}
или
doubleGet(intindex, bool&result) { list *p = m_head;
while (p &&index) { p = p->link; index--; } result = (p != NULL);
return p ? p->data : 0;}
Этот способ используется достаточно часто, однако здесь мы вынуждены изменить сигнатуру функции. Кроме того, для проверки успешности операции в вызывающей функции нужно вводить дополнительную переменную, а автор вызывающей функции может просто забыть или полениться проверить успешность выполнения функции. Еще один способ – использовать специальную переменную (глобальную или переменную- член класса) для сообщения об ошибке.
classСDblList
{
structlist{
doubledata; list* link;
} *m_head;
public:
boolm_succeeded; doubleGet(intindex) {
list *p = m_head;
while (p &&index) { p = p->link; index--; } m_succeeded = (p != NULL);
return p ? p->data : 0;
}…};
Здесь для вызывающей функции нет необходимости заводить дополнительные переменные, но забыть проверить успешность операции еще проще, чем в предыдущем варианте. Кроме того, существуют определенные проблемы при использовании такого способа в многопоточной среде.
Альтернативой описанным выше способам является использование механизма обработки исключений.
Контрольные вопросы
1. Механизм обработки исключений