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