Исключения в 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]
Все остальное, что не попадает ни под одну категорию.

Мини-Опрос
Сколько Вам лет?
Всего ответов: 1684

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

Исключения в 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# | Просмотров: 4568 | Добавил: ДядяВолк (11.08.2010) | Рейтинг: 5.0/2
Источник: http://quadrathell.cn.ua/ |
HTML ссылка на материал:
BB ссылка на материал:
Похожие материалы :
Возможно вам будет интересно:
Урок про скелетную анимацию (0)
Создание света (освещение уровня) (0)
Создание многопользовательской(online) игры на Game Maker. (часть 3) (0)
Как рисовать спрайты в DXDraw DelphiX (0)
Создание MMORPG игр. (3)
Создаем танчики (Урок 2) (0)
Уроки по fps creator'y от scorpion24 (sfsa) (0)
Самообучение ИИ (1)
Создание многопользовательской(online) игры на Game Maker. (часть 5) (1)
Пишем игровой сюжет (10)
Работа с файлами. Открытие файла и чтение из него (0)
Frame by frame в 3d RAD (2)
Создание базового движка для игры. Часть 1. Графика и клавиатура (0)
Функция LIST (0)
3D Rad - система сохранения №1. (0)
Всего комментариев: 0
Добавлять комментарии могут только зарегистрированные пользователи.
[ Регистрация | Вход ]
Поиск
Поиск по всему сайту:
Поиск по разделу:

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


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

Ваш IP: 18.118.126.69

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

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

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

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

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

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