Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
шпоры по ямп.docx
Скачиваний:
10
Добавлен:
01.04.2025
Размер:
162 Кб
Скачать
☆

18.Конструкторы. Деструкторы.

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

1. Конструкторы

Функция-член класса с тем же именем, что и у класса, называется конструктором. Она используется для построения объектов этого класса. Конструктор не должен возвращать никакого значения, даже void.

class Complex

{ private:

double r, m;

public:

Complex(double r, double m) : r(r), m(m) {}

...

};

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

Когда для класса объявлен конструктор, нельзя пользоваться списком инициализации в качестве инициализатора.

Complex c1(5, -2);

Complex c2 = {5, -2};

// Правильно

// Ошибка – класс Complex имеет конструктор

1.1. Конструктор умолчания

Конструктор умолчания класса Х – это конструктор класса Х, вызываемый без параметров. Конструктор умолчания обычно имеет вид Х::Х(), однако и конструктор, который может вызываться без параметров, потому что имеет параметры с умолчанием, например, Х::Х(int = 0), также считается конструктором умолчания. При отсутствии других объявленных конструкторов, конструктор умолчания генерируется компилятором.

class Complex

{ private:

double r, m;

public:

Complex() : r(0), m(0) {}

...

};

Complex x;

// Вызов конструктора умолчания

class Complex

{ private:

double r, m;

public:

Complex(double nr = 0, double nm = 0) : r(nr), m(nm) {}

...

};

Complex y1(-6, 3);

// Вызов конструктора с параметрами

Complex y2;

// Конструктор вызывается как конструктор умолчания

1.2. Конструктор копирования

Конструктор копирования для класса Х – это конструктор, который может быть вызван для копирования объекта класса Х, т.е. такой конструктор, который может быть вызван с одним параметром – ссылкой на объект класса Х. Например, X::X(const X&) и X::X(X&, int = 0) являются конструкторами копирования.

При отсутствии объявленных конструкторов копирования компилятор генерирует публичныйконструктор копирования. Генерируемый конструктор копирования выполняет побитовое копирование объекта. Этот метод годится лишь при отсутствии в объекте указателей, которые хранят адреса динамически распределенной памяти. Сгенерированный конструктор скопирует адрес, а не содержимое памяти, таким образом, два разных объекта будут ссылаться на один и тот участок памяти и меняться синхронно, что не является ожидаемым поведением. В таком случае программист обязательно должен сам написать конструктор копирования, который будет, в частности, копировать содержимое динамически распределённой памяти.

Однако в тех случаях, когда копирующий конструктор по умолчанию имеет правильный смысл, лучше полагаться на это умолчание. Это короче, а читающие код должны понимать умолчания. Кроме того, компилятор знает об этом умолчании и о возможностях его оптимизации. А написание почленного копирования классов с большим количеством членов данных вручную – занятие утомительное, и при этом можно наделать массу ошибок.

Конструктор копирования – и определяемый пользователем, и генерируемый компилятором – используется:

при инициализации переменных;

при передаче аргументов;

при возврате значения из функции;

при обработке исключений.

Семантика этих операций по определению совпадает с семантикой инициализации.

Complex x = 2;

Complex y = Complex(2, 0);

// Создает Complex(2), затем копирует его в x

// Создает Complex(2, 0), затем копирует его в у

От вызовов конструктора копирования легко избавиться. С тем же успехом можно записать следующее.

Complex x(2);

Complex y(2, 0);

// Проинициализировать x значением 2

// Проинициализировать у значением (2, 0)

2. Деструкторы

Функция-член класса Х с именем ~Х называется деструктором. Она используется для разрушения значения класса Х непосредственно перед разрушением содержащего его объекта. Деструктор не имеет параметров и возвращаемого типа, нельзя задавать даже void. Деструкторы автоматически вызываются, когда автоматический или временный объект уходит из области действия; завершается программа (для статически сконструированных объектов); используется операция delete для объектов размещенных операцией new. Деструктор может также вызываться явным образом.

class X

{ private:

int n;

public:

X();

~X();

};

X xx;

xx.~X();

// Явный вызов деструктора