Предопределенные исключения
В библиотеке C++ имеется несколько предопределенных классов исключений. В следующих параграфах мы рассмотрим некоторые из них.
xmsg
Класс xmsg предназначен для передачи строковых сообщений об исключениях. Он объявлен в заголовке except, h:
class EXPCLASS xmsg : public std::exception
{ public:
xmsg(const std::string &msg);
xmsg(const xmsg &);
virtual ~xmsg() throw ();
xmsg & operator=(const xmsg &) ;
virtual const char * what() const throw ();
const std::string & why() const;
void raise () throw(xmsg);
private:
std::string *str;
};
Применять класс xmsg очень просто:
#include <iostream.h>
#include <except.h>
#pragma hdrstop
#include <condefs.h>
int main() {
try {
xmsg X("Exception!");
throw X;
// или
//
X.raise () ;
}
catch(xmsg Smsg) {
cout << "Caught in main: " << msg.why() << end1;
}
return 0;
}
В классе имеется функция-элемент raise (), посредством которой объект выбрасывает сам себя. Ею можно воспользоваться вместо оператора throw. Функция why () возвращает стандартную строку с сообщением, записанным в объект.
Класс xmsg считается устаревшим. Теперь в стандартной библиотеке C++ определяется ряд классов (производных от exception, как и xmsg), организованных иерархически. По сути они ничем друг от друга не отличаются; данные им имена ничего особенного не значат. Вот эти классы: class logic_error public exception class domain_error public logic_error class invalid argument public logic_error class length_error public logic_error class out_of_range public logic_error class runtime error public exception class range error public runtime error class overflow_error public runtime error class underflow error public runtime error
Как видите, logic_error и runtime_error — производные от exception, а все остальные — от первых двух. Эти классы имеют конструктор, принимающий ссылку на стандартную строку, виртуальный деструктор и виртуальную функцию-элемент what (), которая возвращает указатель на константную строку С. Вот пример:
#include <iostream>
#include <stdexcept>
using namespace std;
static void f() ( throw runtime_error("a runtime error");
}
int main ()
{
try
{ f();
}
catch (const exceptions e) {
cout << "Got an exception: " << e.what() << endl;
} return 0;
}
Программа печатает:
Got an exception: a runtime error
Иерархия и полиморфизм этих классов делают их весьма гибким средством организации обработки ошибок.
bad_alloc
Если операция new не может выделить запрашиваемую память, она выбрасывает исключение bad_alloc. Этот класс также является производным от exception:
class bad alloc : public exception {
public:
bad_alloc () throw() : exception () { ; }
bad_alloc(const bad_alioc&) throw()
{ ; }
bad_alloc& operator=(const bad_alloc&) throw()
{ return *this; }
virtual ~bad_alloc () throw ();
virtual const char * what () const throw()
{
return _RWSTD::_rw_stdexcept_BadAilocException;
} };
Продемонстрировать реальную работу этого класса с реальной операцией new вряд ли возможно, да и не стоит. Можно, однако, выбросить bad_alloc вручную:
int main () {
try {
throw bad_alloc();
} catch(const exception &e) (
cout << "Caught something: "<< e.what() “ endl;
}
return 0;
}
Функция what () объекта bad_alloc возвращает строку "bad alloc exception thrown".
В прежних версиях языка new при ошибке выбрасывала xalloc, класс, производный от xmsg:
class _EXPCLASS xalloc : public xmsg
{
public:
xalloc(const std::string &msg, _SIZE_T size);
_SIZE_T requested () const.;
void raise () throw(xalloc);
private:
_SIZE_T siz;
};
Теперь этим классом пользоваться нельзя, и он остался в библиотеке C++Builder только для обеспечения совместимости со старыми библиотеками. Еще раньше операция new при отказе просто возвращала NULL. Такое поведение операции восстановить очень просто, вызвав функцию set_new_hand-ler():
#include <new.h>
set new handler (0);
Прототип set_new_handler () имеет вид
typedef void (*new_handler)();
new_handler set__new_handler(new_handler rny_handler);
Функция предназначена для установки пользовательского обработчика ошибок глобальных операций new или new [ ]. Обработчик my handler может:
В идеале обработчик освобождает ненужную память и возвращает управление. В этом случае new снова попытается удовлетворить запрос.
В следующей главе мы встретимся еще с двумя предопределенными классами исключений — bad_typeid и bad_ typeinfo.