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

// Use of set_terminate()

// Also shows uncaught exceptions

#include

#include

#include

using namespace std;


void terminator() {

  cout << "I'll be back!" << endl;

  exit(0);

}


void (*old_terminate)()

  = set_terminate(terminator);


class Botch {

public:

  class Fruit {};

  void f() {

    cout << "Botch::f()" << endl;

    throw Fruit();

  }

  ~Botch() { throw 'c'; }

};


int main() {

  try {

    Botch b;

    b.f();

  } catch(...) {

    cout << "inside catch(...)" << endl;

  }

} ///:~


The definition of old_terminate looks a bit confusing at first: it not only creates a pointer to a function, but it initializes that pointer to the return value of set_terminate( ). Even though you might be familiar with seeing a semicolon right after a pointer-to-function declaration, here it’s just another kind of variable and can be initialized when it is defined.

The class Botch not only throws an exception inside f( ), but also in its destructor. As we explained earlier, this situation causes a call to terminate( ), as you can see in main( ). Even though the exception handler says catch(...), which would seem to catch everything and leave no cause for terminate( ) to be called, terminate( ) is called anyway. In the process of cleaning up the objects on the stack to handle one exception, the Botch destructor is called, and that generates a second exception, forcing a call to terminate( ). Thus, a destructor that throws an exception or causes one to be thrown is usually a sign of poor design or sloppy coding.

Cleaning up

Part of the magic of exception handling is that you can pop from normal program flow into the appropriate exception handler. Doing so wouldn’t be useful, however, if things weren’t cleaned up properly as the exception was thrown. C++ exception handling guarantees that as you leave a scope, all objects in that scope whose constructors have been completed will have destructors called.

Here’s an example that demonstrates that constructors that aren’t completed don’t have the associated destructors called. It also shows what happens when an exception is thrown in the middle of the creation of an array of objects:.

//: C01:Cleanup.cpp

// Exceptions clean up complete objects only

#include

using namespace std;


class Trace {

  static int counter;

  int objid;

public:

  Trace() {

    objid = counter++;

    cout << "constructing Trace #" << objid << endl;

    if(objid == 3) throw 3;

  }

  ~Trace() {

    cout << "destructing Trace #" << objid << endl;

  }

};


int Trace::counter = 0;


int main() {

  try {

    Trace n1;

    // Throws exception:

    Trace array[5];

    Trace n2;  // won't get here

  } catch(int i) {

    cout << "caught " << i << endl;

  }

} ///:~


The class Trace keeps track of objects so that you can trace program progress. It keeps a count of the number of objects created with a static data member counter and tracks the number of the particular object with objid.

The main program creates a single object, n1 (objid 0), and then attempts to create an array of five Trace objects, but an exception is thrown before the third object is fully created. The object n2 is never created. You can see the results in the output of the program:.

constructing Trace #0

constructing Trace #1

constructing Trace #2

constructing Trace #3

destructing Trace #2

destructing Trace #1

destructing Trace #0

caught 3


Three array elements are successfully created, but in the middle of the constructor for the fourth element, an exception is thrown. Because the fourth construction in main( ) (for array[2]) never completes, only the destructors for objects array[1] and array[0] are called. Finally, object n1 is destroyed, but not object n2, because it was never created.

Resource management

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

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

3ds Max 2008
3ds Max 2008

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

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

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