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

Again, the storage allocation for Dog throws an exception, but this time the array of Cat objects is properly cleaned up, so there is no memory leak.

<p>auto_ptr</p>

Since dynamic memory is the most frequent resource used in a typical C++ program, the standard provides an RAII wrapper for pointers to heap memory that automatically frees the memory. The auto_ptr class template, defined in the header, has a constructor that takes a pointer to its generic type (whatever you use in your code). The auto_ptr class template also overloads the pointer operators * and -> to forward these operations to the original pointer the auto_ptr object is holding. You can, therefore, use the auto_ptr object as if it were a raw pointer. Here’s how it works:.

//: C01:Auto_ptr.cpp

// Illustrates the RAII nature of auto_ptr

#include

#include

using namespace std;

class TraceHeap {

  int i;

public:

  static void* operator new(size_t siz) {

    void* p = ::operator new(siz);

    cout << "Allocating TraceHeap object on the heap "

         << "at address " << p << endl;

    return p;

  }

  static void operator delete(void* p) {

    cout << "Deleting TraceHeap object at address "

         << p << endl;

    ::operator delete(p);

  }

  TraceHeap(int i) : i(i) {}

  int getVal() const {

    return i;

  }

};

int main() {

  auto_ptr pMyObject(new TraceHeap(5));

  cout << pMyObject->getVal() << endl;  // prints 5

} ///:~

The TraceHeap class overloads the operator new and operator delete so you can see exactly what’s happening. Notice that, like any other class template, you specify the type you’re going to use in a template parameter. You don’t say TraceHeap*, however; auto_ptr already knows that it will be storing a pointer to your type. The second line of main( ) verifies that auto_ptr’s operator->( ) function applies the indirection to the original, underlying pointer. Most important, even though we didn’t explicitly delete the original pointer (in fact we can’t here, since we didn’t save its address in a variable anywhere), pMyObject’s destructor deletes the original pointer during stack unwinding, as the following output verifies:.

Allocating TraceHeap object on the heap at address 8930040

5

Deleting TraceHeap object at address 8930040

The auto_ptr class template is also handy for pointer data members. Since class objects contained by value are always destructed, auto_ptr members always delete the raw pointer they wrap when the containing object is destructed[5].

<p>Function-level try blocks</p>

Since constructors can routinely throw exceptions, you might want to handle exceptions that occur when an object’s member or base subobjects are initialized. To do this, you can place the initialization of such subobjects in a function-level try block. In a departure from the usual syntax, the try block for constructor initializers is the constructor body, and the associated catch block follows the body of the constructor, as in the following example.

//: C01:InitExcept.cpp

// Handles exceptions from subobjects

//{-bor}

#include

using namespace std;

class Base {

  int i;

public:

  class BaseExcept {};

  Base(int i) : i(i) {

    throw BaseExcept();

  }

};

class Derived : public Base {

public:

  class DerivedExcept {

    const char* msg;

  public:

    DerivedExcept(const char* msg) : msg(msg) {}

    const char* what() const {

      return msg;

    }

  };

  Derived(int j)

  try

    : Base(j) {

    // Constructor body

    cout << "This won't print\n";

  }

  catch (BaseExcept&) {

    throw DerivedExcept("Base subobject threw");;

  }

};

int main() {

  try {

    Derived d(3);

  }

  catch (Derived::DerivedExcept& d) {

    cout << d.what() << endl;  // "Base subobject threw"

  }

} ///:~

Notice that the initializer list in the constructor for Derived goes after the try keyword but before the constructor body. If an exception does indeed occur, the contained object is not constructed, so it makes no sense to return to the code that created it. For this reason, the only sensible thing to do is to throw an exception in the function-level catch clause.

Although it is not terribly useful, C++ also allows function-level try blocks for any function, as the following example illustrates:

//: C01:FunctionTryBlock.cpp

// Function-level try blocks

//{-bor}

#include

using namespace std;

int main() try {

  throw "main";

} catch(const char* msg) {

cout << msg << endl;

return 1;

} ///:~

In this case, the catch block can return in the same manner that the function body normally returns. Using this type of function-level try block isn’t much different from inserting a try-catch around the code inside of the function body.

<p>Standard exceptions</p>

The set of exceptions used with the Standard C++ library is also available for your use. Generally it’s easier and faster to start with a standard exception class than to try to define your own. If the standard class doesn’t do exactly what you need, you can derive from it.

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

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

1С: Бухгалтерия 8 с нуля
1С: Бухгалтерия 8 с нуля

Книга содержит полное описание приемов и методов работы с программой 1С:Бухгалтерия 8. Рассматривается автоматизация всех основных участков бухгалтерии: учет наличных и безналичных денежных средств, основных средств и НМА, прихода и расхода товарно-материальных ценностей, зарплаты, производства. Описано, как вводить исходные данные, заполнять справочники и каталоги, работать с первичными документами, проводить их по учету, формировать разнообразные отчеты, выводить данные на печать, настраивать программу и использовать ее сервисные функции. Каждый урок содержит подробное описание рассматриваемой темы с детальным разбором и иллюстрированием всех этапов.Для широкого круга пользователей.

Алексей Анатольевич Гладкий

Программирование, программы, базы данных / Программное обеспечение / Бухучет и аудит / Финансы и бизнес / Книги по IT / Словари и Энциклопедии
1С: Управление торговлей 8.2
1С: Управление торговлей 8.2

Современные торговые предприятия предлагают своим клиентам широчайший ассортимент товаров, который исчисляется тысячами и десятками тысяч наименований. Причем многие позиции могут реализовываться на разных условиях: предоплата, отсрочка платежи, скидка, наценка, объем партии, и т.д. Клиенты зачастую делятся на категории – VIP-клиент, обычный клиент, постоянный клиент, мелкооптовый клиент, и т.д. Товарные позиции могут комплектоваться и разукомплектовываться, многие товары подлежат обязательной сертификации и гигиеническим исследованиям, некондиционные позиции необходимо списывать, на складах периодически должна проводиться инвентаризация, каждая компания должна иметь свою маркетинговую политику и т.д., вообщем – современное торговое предприятие представляет живой организм, находящийся в постоянном движении.Очевидно, что вся эта кипучая деятельность требует автоматизации. Для решения этой задачи существуют специальные программные средства, и в этой книге мы познакомим вам с самым популярным продуктом, предназначенным для автоматизации деятельности торгового предприятия – «1С Управление торговлей», которое реализовано на новейшей технологической платформе версии 1С 8.2.

Алексей Анатольевич Гладкий

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