Тема: Исключительные ситуации

ПЛАН ЗАНЯТИЯ №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. Механизм обработки исключений