Конструкторы и деструкторы
Конструкторы и деструкторыКласс может включать функцию конструктора и функцию деструктора. Конструктор вызывается при первоначальном создании объекта класса, а деструктор — при разрушении. Имя конструктора совпадает с именем класса. Функция деструктора имеет имя совпадающее с именем класса, но ему предшествует символ тильда (~). Следующий пример создаёт точку на плоскости с координатами по умолчанию (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".
|