На этом шаге мы рассмотрим обработку исключений средствами C++.
Обработка исключений C++ завершает цепочку команд, начатую SEH. SEH - это системный сервис, а для обработки исключений C++ Вы сами пишете код. Она сложнее и обладает большими возможностями. В приложениях Visual C++ не рекомендуется использовать низкоуровневые ключевые слова __try и __except.
Подобно тому как приложения на языке С используют структурную обработку исключений, в приложениях, созданных с помощью Visual C++, присутствуют обработчики исключений, выполняющиеся при возникновении ошибки. Их код устраняет проблемы и повторяет оператор, вызвавший сбой, полностью игнорирует проблему или передает уведомление дальше по цепочке обработчиков. Для этого в языке C++ существуют ключевые слова try, catch и throw. В отличие от их двойников из SEH, они не предваряются двойным подчеркиванием.
В качестве примера обработки исключений C++ снова рассмотрим случай, когда программа пытается произвести запись в память, не выделенную из-за неуспешного выполнения оператора new. Ранее мы уже показывали, как приложение предотвращает сбой, проверив значение возвращенного указателя. Обработка исключений - более сложное решение проблемы. При этом код разделен на блоки try и catch, вместо множества вложенных блоков IF-ELSE, что и демонстрирует следующий пример:
try { int *iptr = new int[BLOCK_SIZE]; //Если была достигнута эта строка, выделить память удалось delete []iptr; } catch(CMemoryException* e) { //Выделить память не удалось, реагируем на ошибку e->Delete(); }
Если оператору new не удастся выделить память, он вызовет исключение, что приведет к выполнению блока catch. В примере блок catch принимает в качестве параметра MFC-объект CMemoryException с информацией о причинах проблем, вызванных оператором new. В программах, не применяющих MFC, для этой цели можно создать собственные классы или же применять указатели на стандартные типы данных, например на строки. Параметром блока может быть и конструкция (...), которая указывает компилятору на то, что блок catch обрабатывает исключения любого типа, а не только связанные с памятью.
Если блоку catch удалось исправить ошибку, он попытается снова выполнить инструкцию блока try, вызвавшую исключение. Это намного удобнее использования фильтра EXCEPTION_CONTINUE_EXECUTION в SEH, так как блок catch все-таки выполняется. Если блок catch не получает исключения повторно, программа продолжает свою работу, переходя на следующий за ним оператор.
На следующем шаге мы рассмотрим макросы исключений.