Генерация исключений в конструкторах

Механизм обработки исключительных ситуаций очень удобен для обработки ошибок, возникающих в конструкторах. Так как конструктор не возвращает значения, то соответственно нельзя возвратить некий код ошибки и приходится искать альтернативу. В этом случае наилучшим решением является генерация и обработка исключительной ситуации. При генерации исключения внутри конструктора процесс создания объекта прекращается. Если к этому моменту были вызваны конструкторы базовых классов, то будет обеспечен и вызов соответствующих деструкторов. Рассмотрим на примере генерацию исключительной ситуации внутри конструктора. Пусть имеется класс В, производный от класса А и содержащий в качестве компоненты-данного объект класса local. В конструкторе класса В генерируется исключительная ситуация.

#include<iostream>

using namespace std;

class local

{ public:

local() { cout<<"Constructor of local"<<endl; }

~local() { cout<<"Destructor of local"<<endl; }

};

class A

{ protected:

int n;

public:

A() { cout<<"Constructor of A"<<endl; }

virtual ~A() { cout<<"Destructor of A"<<endl; }

virtual void f()=0;

};

class B : public A

{ public:

local ob;

B(int i=0)

{ cout<<"Constructor of B"<<endl;

if(i) throw 1;

n=i;

}

~B() {cout<<"Destructor of B"<<endl; }

void f(){cout<<"** "<<n<<" **"<<endl;}

};

int main()

{ A *p;

try {

p=new B(1);

p->f();

}

catch(int) {

cout<<"int exception handler"<<endl;

return 1;

}

p->f();

delete p;

return 0;

}

Результат выполнения программы:

Constructor of A

Constructor of local

Constructor of B

int exception handler

Destructor of local

Destructor of A

В программе при создании объекта производного класса В сначала вызываются конструкторы базового класса А, затем класса local, который является компонентом класса В. После этого вызывается конструктор класса В, в котором генерируется исключительная ситуация. При выходе из области видимости ( try{} ) деструкторы не вызываются, так как объекты являются динамическими. При выполнении инструкции

delete p;

выполняется вызов деструкторов. Видно, что при этом для всех ранее созданных объектов вызваны деструкторы, а для объекта самого класса В деструктор не вызывается, так как конструирование этого объекта не было завершено.

Если в конструкторах выполнялось динамическое выделение памяти, то при генерации исключительной ситуации выделенная память автоматически освобождена не будет, об этом необходимо заботиться самостоятельно, иначе возникнет утечка памяти.