Исключения в C++ - C, C++, C# - Программирование
Навигация по сайту
Сайт:

Дополнительно:

Файловый архив:

Каталог статей:

Форум:


Категории раздела
Delphi, Pascal, ObjectPascal [18]
Программирование на Delphi, Pascal, ObjectPascal
C, C++, C# [7]
Программирование на C, C++, C#
ПХП (PHP) [6]
Все что связано с программированием на PHP.
DirectX [0]
Программирование с использованием графического API DirectX
OpenGL [0]
Программирование с использованием графического API OpenGL
Работа с базами данных (БД) [0]
Работа с базами данных MySQL и т.д. Разработка, теории, алгоритмы.
Сетевое программирование [0]
Сетевое программирование, организация сетей.
Программирование игр [0]
Все что связано с программированием игр, организацией их разработки.
Работа с мультимедиа данными [0]
Загрузка, обработка, воспроизведение и все что связано со звуком и видео.
Работа с устройсвами ввода и вывода [0]
Программирование устройств ввода и вывода. Работа с геймпадом, рулем и многим другим.
Программирование HTML 5 игр [0]
Программирование HTML 5 игр, html верстка, JS (JavaScript)
Остальное [0]
Все остальное, что не попадает ни под одну категорию.

Мини-Опрос
Какой платформой Вы пользуетесь?
Всего ответов: 1025

Партнеры сайта
....

Исключения в C++

20:59
Язык С представляет программисту очень ограниченные возможности обработки исключений, возникших при работе программы. В этом отношении С++ намного развитее С. Здесь у программиста существенно большие возможности по непосредственной обработке исключений. Комитет по разработке стандартов С++ предоставил очень простую, но мощную форму обработки исключений.

Типичная функция, написанная на С, выглядит примерно так:

long DoSomething()
{
long *a, c;
FILE *b;
a = malloc(sizeof(long) * 10);
if (a == NULL)
return 1;
b = fopen("something.bah", "rb");
if (b == NULL) {
free(a);
return 2;
}
fread(a, sizeof(long), 10, b);
if (a[0] != 0x10) {
free(a);
fclose(b);
return 3;
}
fclose(b);
c = a[1];
free(a);
return c;
}
Выглядит не очень, не так ли? Вы целиком и полностью зависите от значений, которые возвращают вам функции и для каждой ошибки вам постоянно нужен код, который ее обрабатывает. Если вы, скажем, в функции работаете хотя бы с 10 указателями (рапределяете память, освобождаете ее и т.д.), то наверняка половину кода функции будет занимать код обработки ошибок. Такая же ситуация будет в коде, вызывающем эту функцию, так как здесь также нужно обработать все возвращаемые коды ошибок.

Try-catch-throw

Давайте же разберем основы обработки исключений в С++. Чтобы комфортно работать с исключениями в С++ вам нужно знать лишь три ключевых слова:

try (пытаться) - начало блока исключений;
catch (поймать) - начало блока, "ловящего" исключение;
throw (бросить) - ключевое слово, "создающее" ("возбуждающее") исключение.
А теперь пример, демонстрирующий, как применить то, что вы узнали:

void func()
{
try
{
throw 1;
}
catch(int a)
{
cout << "Caught exception number: " << a << endl;
return;
}
cout << "No exception detected!" << endl;
return;
}
Если выполнить этот фрагмент кода, то мы получим следующий результат:

Caught exception number: 1
Теперь закоментируйте строку throw 1; и функция выдаст такой результат:

No exception detected!
Как видите все очень просто, но если это применить с умом, такой подход покажется вам очень мощным средством обработки ошибок. Catch может "ловить" любой тип данных, так же как и throw может "кинуть" данные любого типа. Т.е. throw AnyClass(); будет правильно работать, так же как и catch (AnyClass &d) {};.

Как уже было сказано, catch может "ловить" данные любого типа, но вовсе не обязательно при это указывать переменную. Т.е. прекрасно будет работать что-нибудь типа этого:

catch(dumbclass) { }
так же, как и

catch(dumbclass&) { }
Так же можно "поймать" и все исключения:

catch(...) { }
Троеточие в этом случае показывает, что будут пойманы все исключения. При таком подходе нельзя указать имя переменной. В случае, если "кидаются" данные нестандартного типа (экземпляры определенных вами классов, структур и т.д.), лучше "ловить" их по ссылке, иначе вся "кидаемая" переменная будет скопирована в стек вместо того, чтобы просто передать указатель на нее. Если кидаются данные нескольких типов и вы хотите поймать конкретную переменную (вернее, переменную конкретного типа), то можно использовать несколько блоков catch, ловящих "свой" тип данных:

try {
throw 1;
// throw 'a';
}
catch (long b) {
cout << "пойман тип long: " << b << endl;
}
catch (char b) {
cout << "пойман тип char: " << b << endl;
}"
Создание" исключений

Когда возбуждается исключительная ситуация, программа просматривает стек функций до тех пор, пока не находит соответствующий catch. Если оператор catch не найден, STL будет обрабатывать исключение в стандартном обработчике, который делает все менее изящно, чем могли бы сделать вы, показывая какие-то непонятные (для конечного пользователя) сообщения и обычно аварийно завершая программу.

Однако более важным моментом является то, что пока просматривается стек функций, вызываются деструкторы всех локальных классов, так что вам не нужно забодиться об освобождении памяти и т.п.

Перегрузка глобальных операторов new/delete

А сейчас хотелось бы отправить вас к статье "Как обнаружить утечку памяти". В ней рассказывается, как обнаружить неправильное управление распределением памяти в вашей программе. Вы можете спросить, при чем тут перегрузка операторов? Если перегрузить стандартные new и delete, то открываются широкие возможности по отслеживанию ошибок (причем ошибок часто критических) с помощью исключений. Например:

char *a;
try
{
a = new char[10];
}
catch (...){
// a не создан - обработать ошибку распределения памяти,
// выйти из программы и т.п.
}
// a успешно создан, продолжаем выполнение
Это, на первый взгляд, кажется длиннее, чем стандартная проверка в С "а равен NULL?", однако если в программе выделяется десяток динамических переменных, то такой метод оправдывает себя.

Операторы throw без параметров

Итак, мы увидели, как новый метод обработки ошибок удобен и прост. Блок try-catch может содержать вложенные блоки try-catch и если не будет определено соответствующего оператора catch на текущем уровен вложения, исключение будет поймано на более высоком уровне. Единственная вещь, о которой вы должны помнить, - это то, что операторы, следующие за throw, никогда не выполнятся.

try
{
throw;
// ни один оператор, следующий далее (до закрывающей скобки)
// выполнен не будет
}
catch(...)
{
cout << "Исключение!" << endl;
}
Такой метод может применяться в случаях, когда не нужно передавать никаких данных в блок catch.

Приложение

Приведем пример, как все вышеизложенное может быть использовано в конкретном приложении. Преположим, у вас в программе есть класс cMain и экземпляр этого класса Main: class cMain { public: bool Setup(); bool Loop(); // Основной цикл программы void Close(); }; cMain Main;

А в функции main() или WinMain() вы можете использовать этот класс как-нибудь так:

try
{
Main.Setup();
Main.Loop();
Main.Close();
}
catch (Exception &e)
{
// использование класса, ведущего лог.
log("Exception thrown: %s", e.String());

// Показываем сообщение об ошибке и закрываем приложение.
}
Основной цикл программы может выглядеть примерно так:

while (AppActive)
{
try
{
// какие-то действия
}
catch (Exception &e)
{
/* Если исключение критическое, типа ошибки памяти,
посылаем исключение дальше, в main(), оператором throw e;
или просто throw.
Если исключение некритично, обрабатываем его и
возвращаемся в основной цикл. */
}
}


Категория: C, C++, C# | Просмотров: 4424 | Добавил: ДядяВолк (11.08.2010) | Рейтинг: 5.0/2
Источник: http://quadrathell.cn.ua/ |
HTML ссылка на материал:
BB ссылка на материал:
Похожие материалы :
Возможно вам будет интересно:
Frame by frame в 3d RAD (2)
Создание 3D игр на Game Maker (3)
Создание RTS игры (2)
Создание заставки (Intro) (0)
Borland Assembler (BASM) уроки для начинающих (урок 6) (0)
PHP и MySQL – Теоретический курс. Введение. (2)
Создание наземного врага в платформере (2)
Полезные функции и процедуры: часть 1 (0)
Начинаем изучать PHP (4)
Переменные в Actionscript 2.0 (0)
Borland Assembler (BASM) уроки для начинающих (уроки 1-4) (0)
С чего начать создание игры для начинающих? (13)
Работа с инифайлами (*.ini) (0)
Самообучение ИИ (1)
Золотые Правила Игродела (0)
Всего комментариев: 0
Добавлять комментарии могут только зарегистрированные пользователи.
[ Регистрация | Вход ]
Поиск
Поиск по всему сайту:
Поиск по разделу:

Панель пользователя
Здравствуйте, Гость


Ник:
Пароль:
Запомнить :

Ваш IP: 3.235.42.157

Случайные конструкторы

Случайные движки

Случайные статьи

Статистика
Онлайн всего: 1
Гостей: 1
Пользователей: 0

На сайте были:

При полном или частичном копировании материалов сайта ссылка на Make-Games.ru обязательна. Make-Games.ru © 2008 - 2024 Хостинг от uCoz
Топ Разработка игр