Главная страница Случайная страница Разделы сайта АвтомобилиАстрономияБиологияГеографияДом и садДругие языкиДругоеИнформатикаИсторияКультураЛитератураЛогикаМатематикаМедицинаМеталлургияМеханикаОбразованиеОхрана трудаПедагогикаПолитикаПравоПсихологияРелигияРиторикаСоциологияСпортСтроительствоТехнологияТуризмФизикаФилософияФинансыХимияЧерчениеЭкологияЭкономикаЭлектроника |
Конструктори та деструктори
Лекція 6
План 1. Поняття конструкторів та деструкторів.
1. Поняття конструкторів та деструкторів.
Конструкторы и деструкторы - это специальные методы класса. Это надо понять в первую очередь. Разумеется, эти методы обладают целым рядом особенностей (именно по этому они и выделены в специальную группу). Сейчас мы об этих особенностях и поговорим. Первое. В отличие от других методов они должны называться особым образом. Если обычные методы могут называться как угодно, то имя констуктора должно совпадать с именем класса, а имя деструктора - с именем класса с приписанной в начале тильдой. Например, если класс называется CRect, то конструктор этого класса обязан называться тоже CRect, а деструктор - ~CRect. Второе. В отличии от других методов конструктор и деструктор вызываются сами (а другие методы мы вызываем явным образом). Конструктор вызывается в момент создания экземпляра класса, а деструктор - в момент уничтожения. Т. е. их не надо вызывать явным образом - они вызываются сами. Именно поэтому конструкторы обычно используются для задания некоторых начальных значений для переменных класса, а деструкторы - для освобождения памяти (в случае если у вас есть внутри класса переменные-указатели). Третье. Ни конструктор, ни деструктор не возвращают никакого значения (даже типа void). Это означает, в частности, что при обяъвлении конструтора и деструктора в классе мы перед ними не пишем ни какой тип. Четвертое. В классе может быть несколько конструкторов (и они должны различаться параметрами), и только один деструктор (у него параметров вообще быть не может). Прежде всего хочется указать на одну из самых распространённых ошибок начинающих: они считают, что конструктор выделяет память для объекта, а деструктор - освобождает. Это неверно! Процесс выделения памяти для объекта следующий: Автоматический объект. Время жизни начинается в момент входа в процедуру или лексический блок, в котором объявлен объект и заканчивается при выходе из процедуры или лексического блока. Статический объект, попавший в исполняемый файл. Время жизни начинается до входа в процедуру main и заканчивается после выхода из процедуры main Статический объект, попавший в динамическую библиотеку. Время жизни начинается с момента загрузки динамической библиотеки и заканчивается в момент выгрузки динамической библиотеки. Динамический объект. Время жизни начинается в момент явного выделения памяти для объекта и заканчивается в момент явного освобождения памяти. Если память явным образом не освобождается, то данная память так и остаётся использованной и будет высвобождена средствами операционной системы. А конструктор только инициализирует объект (т.е. задаёт объекту некоторое начальное значение). Очень важно это понимать. Непонимание обычно растёт из того, что эти два этапа с точки зрения языка обычно выглядят в виде одного оператора. Компилятор обеспечивает механизм, при котором в процессе создания объекта выделяется память под объект и вызывается метод-конструктор. Но эти две вещи не обязательно выполняются подряд одна за другой. Аналогично в процессе удаления объект вызывается метод-деструктор и затем происходит высвобождение памяти.
2.Формат конструктора та деструктора в С++. Примеры конструкторов: class T { private: int x, y; public: T (int _x, int _y) { x = _x; y = _y; } /* Смысла в этом деструкторе нет, но пишу его в таком виде, чтобы он был не пустой */ ~T () { x = 0; y = 0; } } void func (void) { T a(10, 11), b(20, 21);
/* тело процедуры */ }
По синтаксису языка конструкторы и деструкторы выглядят как процедуры. Техническая их реализация (т.е. реализация в виде кода) ничем не отличается от реализации обычной процедуры. Однако с точки зрения языка Си++ конструктор функцией НЕ является, а потому нельзя вызывать конструктор " ручками" и нельзя брать адрес на конструктор. Логика такого поведения следующая: конструктор является механизмом инициализации объекта, а инициализация является составной частью процесса порождения объекта. И, таким образом, конструктор может вызываться только непосредственно в момент рождения объекта. С деструкторами логика ровно такая же, однако по языку деструктор можно вызывать " ручками" и брать на него адрес. Такое поведени обусловлено тем, что в языке Си++ существует оператор new, который выделяет память не абы где, а использует ту память, которую ему навязал программист Пример №2 #include < iostream>
class T { int x; public: T() { std:: cout < < " constr\n"; } ~T() { std:: cout < < " destr\n"; } };
int main (void) { char *buf = new char[sizeof(T)]; T *t = new(buf) T;
t-> ~T(); } Пример №3: class mod_int { public: mod_int(int i); //объявление контруктора void assign(int i) { v = i % modulus; } void print () const { cout < < v < < '\t'; } const static int modulus = 60; private: int v; }; //определение конструктора mod_int:: mod_int(int i) { v = i % modulus; } const int mod_int:: modulus; Целая переменная v ограничена значениями 0, 1, 2.....modulus - 1. Ответственность за выполнение этого ограничения лежит на программисте; все функции-члены должны вести себя, соблюдая это правило. Функция-член mod_int:: mod_int (int) является конструктором. Она не имеет возвращаемого типа. Она вызывается, когда объявляются объекты THnamod_int. Это функция одного аргумента. При вызове конструктор ожидает выражение, преобразуемое по умолчанию к его целому параметру. Затем он создает и инициализует объявленную переменную. Вот некоторые примеры объявлений с использованием данного типа: mod_int а(0); //a.v = О mod_int Ь(61); //a.v = 1 mod_int а; //недопустимо, т.к. нет списка параметров Поскольку у этого класса лишь один конструктор со списком аргументов int, объявление mod_int должно получать целое выражение, передаваемое в качестве инициа-лизующего значения. Заметьте, что не допуская объявления переменной типа mod_int без выражения-инициализатора, мы тем самым предотвращаем ошибки на этапе выполнения из-за неинициализованных переменных.
3.Типи конструкторів
|