Правила программирования на Си и Си++


         

161. Возбуждение исключений из конструктора ненадежно - часть 4


будет содержать истину, если объект получен не при помощи new, и исключение возбуждено из конструктора, и ложь —

если объект получен посредством new, потому что деструктор еще не вызван.

Конечно, вы можете вполне резонно заметить, что у меня нет причин проверять содержимое объекта, который по теории должен быть уничтожен. Здесь уже другая проблема. Некоторые компиляторы (в том числе компилятор Microsoft Visual C++ 2.2) вызывают деструктор после выполнения оператора catch, даже если объекты, определенные в try-блоке, недоступны из catch-блока. Следовательно, код из листинга 16 не будет работать после этих компиляторов. Вероятно, лучшие решение состояло бы в написании варианта operator new(), который мог бы надежно указывать, получена память из кучи или из стека.


Листинг 16. except.cpp — возбуждение исключения из конструктора

class с

2  {

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;




Содержание  Назад  Вперед