Конструкторы и деструкторы

Конструкторы и деструкторы

Класс может включать функцию конструктора и функцию деструктора. Конструктор вызываеться при первоначальном создании объекта класса, а деструктор — при разрушении. Имя конструктора совпадает с именем класса. Функция деструктора имеет имя совпадающеи с именем класса, но ему предшествует символ тильда (~). Следующий пример создаёт точку на плоскости с координатами по умолчанию (0; 0), а при уничтожении выводит сообщение.

Копировать
class point{
	int x, y;
public:
	point (int mx = 0, int my = 0){
		x = mx;
		y = my;
	}
	~point (void){
		cout << "точка уничтожана";
	}
};

Спецификатор expliclt

Спецификатор expliclt применяеться только к конструкторам. Конструктор, определённый с помощью спецификатора expliclt, будет использоваться только в том случае, если инициализация в точности совпадает с тем, что задано конструктором. Никаких автоматических преобразований выполнено не будет (т.е. спецификатор expliclt создаёт "неконвертирующий конструктор").

Порядок вызова конструкторов

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

При множественном наследовании, при объявлении призводного класса базовые классы перечисляються через запятую. Причём при создании объекта конструкторы выполняються в порядке следования базовых классов слева направо. Например.

Копировать
class B1{
public:
	B1(){ cout << "B1 "; }
};
class B2{
public:
	B2(){ cout << "B2 "; }
};
class D: B1, B2{
public:
	D(){ cout << "D"; }
};

D d;	//создание объекта
Выведет: "B1 B2 D".

Виртуальные деструкторы

Довольно типичная ситуация, когда динамически создаёться объект производного класс, а указатель используеться базового класса. При уничтожении объекта вызываеться деструктор только базового класса. Например.

Копировать
class Base{
public:
	Base(){ cout << "B "; }
	~Base(){ cout << "B "; }
};
class Derive: Base{
public:
	Derive(){ cout << "D "; }
	~Derive(){ cout << "~D "; }
};

Base *p = new Derive;
delete p;
Выведет: "B D ~B".

Чтобы не допускать таких ситуаций необходимо использовать виртуальный деструктор. Если при объявлении деструктора базового класса он объявляеться как виртуальный, то все конструкторы производных классов также являються виртуальными. При разрушении объекта с помощью оператора delete через указатель на базовый класс будут коректно вызваны деструкторы производных классов.
Копировать
class Base{
public:
	virtual Base(){ cout << "B "; }
	~Base(){ cout << "B "; }
};
class Derive: Base{
public:
	Derive(){ cout << "D "; }
	~Derive(){ cout << "~D "; }
};

Base *p = new Derive;
delete p;
Выведет: "B D ~D ~B".