будет содержать истину, если объект получен не при помощи new, и исключение возбуждено из конструктора, и ложь —
если объект получен посредством new, потому что деструктор еще не вызван.
Конечно, вы можете вполне резонно заметить, что у меня нет причин проверять содержимое объекта, который по теории должен быть уничтожен. Здесь уже другая проблема. Некоторые компиляторы (в том числе компилятор Microsoft Visual C++ 2.2) вызывают деструктор после выполнения оператора catch, даже если объекты, определенные в try-блоке, недоступны из catch-блока. Следовательно, код из листинга 16 не будет работать после этих компиляторов. Вероятно, лучшие решение состояло бы в написании варианта operator new(), который мог бы надежно указывать, получена память из кучи или из стека.
Листинг 16. except.cpp — возбуждение исключения из конструктора
1 class с
2 {
3 public:
4 class error
5 {
6 c *p; // NULL при успешном выполнении конструктора
7 public:
8 error( c *p_this );
9 void destroy( void );
10 };
11
12 private:
13
14 unsigned has_been_destroyed : 1;
15 int *pi;
16
17 private: friend
class error;
18 int been_destroyed( void );
19
20 public:
21 c() ;
22 ~c();
23
24 };
25 //========================================================
26 c::error::error( c *p_this ) : p( p_this ) {}
27 //--------------------------------------------------------
28 void
c::error::destroy( void )
29 {
30 if( p && !p->been_destroyed() )
31 delete
p;
32 }
33 //========================================================
34 c::c() : has_been_destroyed( 0 )
35 {
36 // ...
37 throw
error(this);
38 // ...
39 }
40 //--------------------------------------------------------
41 c::~c()
42 {
43 // ...
44 has_beeb_destroyed = 1;
45 }
46 //--------------------------------------------------------
47 int
c::been_destroyed( void )
48 {
49 return has_been_destroyed;