Читаем Thinking In C++. Volume 2: Practical Programming полностью

Only the Up and Fit exceptions are caught because those are the only exceptions that the programmer of f( ) said would be thrown. Version two of g( ) causes my_unexpected( ) to be called because f( ) then throws an int.

In the call to set_unexpected( ), the return value is ignored, but it can also be saved in a pointer to function and be restored later, as we did in the set_terminate( ) example earlier in this chapter.

A typical unexpected handler logs the error and terminates the program by calling exit( ). It can, however, throw another exception (or re-throw the same exception) or call abort( ). If it throws an exception of a type allowed by the function whose specification was originally violated, the search resumes at the call of the function with this exception specification. (This behavior is unique to unexpected( ).)

If the exception thrown from your unexpected handler is not allowed by the original function’s specification, one of the following occurs:

1.       If std::bad_exception (defined in ) was in the function’s exception specification, the exception thrown from the unexpected handler is replaced with a std::bad_exception object, and the search resumes from the function as before.

2.      If the original function’s specification did not include std::bad_exception, terminate( ) is called.

The following program illustrates this behavior.

//: C01:BadException.cpp

//{-bor}

#include     // for std::bad_exception

#include

#include

using namespace std;


// Exception classes:

class A {};

class B {};


// terminate() handler

void my_thandler() {

  cout << "terminate called\n";

  exit(0);

}


// unexpected() handlers

void my_uhandler1() {

  throw A();

}

void my_uhandler2() {

  throw;

}


// If we embed this throw statement in f or g,

// the compiler detects the violation and reports

// an error, so we put it in its own function.

void t() {

  throw B();

}


void f() throw(A) {

  t();

}

void g() throw(A, bad_exception) {

  t();

}


int main() {

  set_terminate(my_thandler);

  set_unexpected(my_uhandler1);

  try {

    f();

  }

  catch (A&) {

    cout << "caught an A from f\n";

  }

  set_unexpected(my_uhandler2);

  try {

    g();

  }

  catch (bad_exception&) {

    cout << "caught a bad_exception from g\n";

  }

  try {

    f();

  }

  catch (...) {

    cout << "This will never print\n";

  }

} ///:~


The my_uhandler1( ) handler throws an acceptable exception (A), so execution resumes at the first catch, which succeeds. The my_uhandler2( ) handler does not throw a valid exception (B), but since g specifies bad_exception, the B exception is replaced by a bad_exception object, and the second catch also succeeds. Since f does not include bad_exception in its specification, my_thandler( ) is called as a terminate handler. Thus, the output from this program is as follows:.

caught an A from f

caught a bad_exception from g

terminate called


Better exception specifications?

You may feel that the existing exception specification rules aren’t very safe, and that

void f();


should mean that no exceptions are thrown from this function. If the programmer wants to throw any type of exception, you might think he or she should have to say.

void f() throw(...); // Not in C++


This would surely be an improvement because function declarations would be more explicit. Unfortunately, you can’t always know by looking at the code in a function whether an exception will be thrown—it could happen because of a memory allocation, for example. Worse, existing functions written before exception handling was introduced may find themselves inadvertently throwing exceptions because of the functions they call (which might be linked into new, exception-throwing versions). Hence, the uninformative situation whereby.

void f();


means, "Maybe I’ll throw an exception, maybe I won’t." This ambiguity is necessary to avoid hindering code evolution. If you want to specify that f throws no exceptions, use the empty list, as in:.

void f() throw();


Exception specifications and inheritance

Перейти на страницу:

Похожие книги

3ds Max 2008
3ds Max 2008

Одни уверены, что нет лучшего способа обучения 3ds Мах, чем прочитать хорошую книгу. Другие склоняются к тому, что эффективнее учиться у преподавателя, который показывает, что и как нужно делать. Данное издание объединяет оба подхода. Его цель – сделать освоение 3ds Мах 2008 максимально быстрым и результативным. Часто после изучения книги у читателя возникают вопросы, почему не получился тот или иной пример. Видеокурс – это гарантия, что такие вопросы не возникнут: ведь автор не только рассказывает, но и показывает, как нужно работать в 3ds Мах.В отличие от большинства интерактивных курсов, где работа в 3ds Мах иллюстрируется на кубиках-шариках, данный видеокурс полностью практический. Все приемы работы с инструментами 3ds Мах 2008 показаны на конкретных примерах, благодаря чему после просмотра курса читатель сможет самостоятельно выполнять даже сложные проекты.

Владимир Антонович Верстак , Владимир Верстак

Программирование, программы, базы данных / Программное обеспечение / Книги по IT