Освой самостоятельно С++ за 21 день.
Шрифт:
Резюме
Сегодня вы узнали, как создавать и использовать исключения, т.е. объекты, которые могут быть созданы в тех местах программы, где исполняемый код не может обработать ошибку или другую исключительную ситуацию, возникшую во время выполнения программы. Другие части программы, расположенные выше в стеке вызовов, выполняют блоки catch, которые перехватывают исключение и отвечают на возникшую исключительную ситуацию соответствующим образом.
Исключения — это нормальные созданные пользователем объекты, которые можно передавать в функции как значения или как ссылки. Они
Можно создать конструкции из нескольких блоков catch, но следует учитывать, что, как только исключение будет перехвачено отдельным оператором catch, оно не будет передаваться последующим блокам catch. Очень важно правильно упорядочить блоки catch, чтобы специфические блоки стояли выше более общих блоков.
На этом занятии также рассматривались некоторые основные принципы работы символьных отладчиков, включая использование таких средств, как точки останова, анализ значений переменных и т.д. Эти средства позволяют выполнить останов программы в той части, которая вызывает появление ошибки, и просмотреть значения переменных в ходе программы.
Вопросы и ответы
Зачем тратить время на программирование исключений? Не лучше ли устранять ошибки по мере их возникновения?
Часто одна и та же ошибка может возникать при выполнении разных функций программы. Использование исключений позволяет собрать коды отслеживания ошибок в одном месте программы. Кроме того, далеко не всегда возможно вписать код устранения ошибки в том месте программы, где эта ошибка возникает.
Зачем создавать исключения как объекты? Не проще ли записать код устранения ошибки?
Объекты более гибки и универсальны в использовании, чем обычные программные блоки. С объектами можно передать больше информации и снабдить конструктор и деструктор класса исключения функциями устранения возникшей ошибки.
Почему бы не использовать исключения не только для отслеживания исключительных ситуаций, но и для выполнения рутинных процессов? Разве не удобно использовать исключения для быстрого и безопасного возвращения по стеку вызовов к исходному состоянию программы?
Безусловно, и многие программисты на C++ используют исключения именно в этих целях. Но следует помнить, что прохождение исключения по стеку вызовов может оказаться не таким уж безопасным. Так, если объект был создан в области динамического обмена, а потом удален в стеке вызовов, это может привести к утечке памяти. Впрочем, при тщательном анализе программы и использовании современного компилятора эту проблему можно предупредить.
Кроме того, многие программисты считают, что использование исключений не по прямому назначению делает программу слишком запутанной и нелогичной.
Всегда ли следует перехватывать исключения сразу за блоком try, генерирующим это исключение?
Нет, в стеке вызовов перехват исключения может осуществляться в любом месте, после чего стек вызовов будет пройден то того места, где происходит обработка исключения.
Зачем использовать утилиту отладки, если те же функции можно осуществлять прямо во время компиляции с помощью объекта cout и условного выражения #ifdef debug?
В действительности утилита отладки предоставляет значительно больше средств и возможностей, таких как пошаговое выполнение программы, установка точек останова и анализ текущих значений переменных. При этом вам не приходится перегружать свой код многочисленными командами препроцессора и выражениями, которые никак не связаны с основным назначением программы.
Коллоквиум
В этом разделе предлагаются вопросы для самоконтроля и укрепления полученных знаний, а также ряд упражнений, которые помогут закрепить ваши практические навыки. Попытайтесь самостоятельно ответить на вопросы теста и выполнить задания, а потом сверьте полученные результаты с ответами в приложении Г. Не приступайте к изучению материала следующей главы, если для вас остались неясными хотя бы некоторые из предложенных ниже вопросов.
Контрольные вопросы
1. Что такое исключение?
2. Для чего нужен блок try?
3. Для чего используется оператор catch?
4. Какую информацию может содержать исключение?
5. Когда создается объект исключения?
6. Следует ли передавать исключения как значения или как ссылки?
7. Будет ли оператор catch перехватывать производные исключения, если он настроен на базовый класс исключения?
8. Если используются два оператора catch, один из которых настроен на базовое сообщение, а второй — на производное, то в каком порядке их следует расположить?
9. Что означает оператор catch(...)?
10. Что такое точка останова?
Упражнения
1. Запишите блок try и оператор catch для отслеживания и обработки простого исключения.
2. Добавьте в исключение, полученное в упражнении 1, переменную-член и метод доступа и используйте их в блоке оператора catch.
3. Унаследуйте новое исключение от исключения, полученного в упражнении 2. Измените блок оператора catch таким образом, чтобы в нем происходила обработка как производного, так и базового исключений.
4. Измените код упражнения 3, чтобы получить трехуровневый вызов функции.
5. Жучки: что не правильно в следующем коде?
#include "string" //класс строк
сlass xOutOfMemory
{
public:
xOutOfMemory{ theMsg = new сhar[20];
strcpy(theMsg, "trror in momory");}
~xOutOfMemory{ delete [] theMsg;
cout << "Memory restored, " << endl; }
char * Message { return theMsg; }
private:
char >> theMsg;
};
main
{
try
{
char * var = new char;
if ( var == 0 )
{
xOutOfMemory * px = new xOutOfMemory;
throw px;
}
}
catch( xOutOfMemory * theException )
{
cout << theException->Message <<endl;
delete theException;
}
return 0;
}
6. Данный пример содержит потенциальную ошибку, подобную возникающей при попытке выделить память для показа сообщения об ошибке в случае обнаружения нехватки свободной памяти. Вы можете протестировать эту программу, изменив строку if (var == 0) на if (1), которая вызовет создание исключения.