C++ Программирование в среде С++ Builder 5

Предопределенные исключения


В библиотеке 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 может:

  • освободить память (удалить какой-то мусор) и возвратить управление;


  • вызвать функцию abort () или exit ();


  • выбросить исключение bad_alloc или производного типа.


  • В идеале обработчик освобождает ненужную память и возвращает управление. В этом случае new снова попытается удовлетворить запрос.

    В следующей главе мы встретимся еще с двумя предопределенными классами исключений — bad_typeid и bad_ typeinfo.


    Содержание раздела