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

Язык C++ / Конструкторы и деструкторы

Конструктор - функция, предназначенная для инициализации объектов класса.Рассмотрим класс date:

class date {
  int day, month, year;
public:
  set(int, int, int);
};

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

class date  {
  int day, month, year;
public:
  date(int, int, int); // конструктор
};

Если конструктор требует аргументы, их следует указать:

date today = date(6,4,2014);
date xmas(25,12,0); // сокращенная форма (xmas - рождество)
// date my_burthday; // недопустимо, опущена инициализация

Если необходимо обеспечить несколько способов инициализации объектов класса, задается несколько конструкторов:

class date {
 int month, day, year;
public:
 date(int, int, int); // день месяц год
 date(char*); // дата в строковом представлении
 date(); // дата по умолчанию: сегодня
};

Конструкторы подчиняются тем же правилам относительно типов параметров, что и перегруженные функции. Если конструкторы существенно различаются по типам своих параметров, то компилятор при каждом использовании может выбрать правильный:

date july4("Февраль 27, 2014");
date guy(27, 2, 2014);
date now; // инициализируется по умолчанию

Одним из способов сократить количество перегруженных функций (в том числе и конструкторов) является использование значений по умолчанию.

Конструктор по умолчанию

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

class date {
  int month, day, year;
public:
  date(int, int, int);
  date(char*);
  date(); // конструктор по умолчанию
};

При создании объекта вызывается конструктор, за исключением случая, когда объект создается как копия другого объекта этого же класса, например:

date date2 = date1;

Однако имеются случаи, в которых создание объекта без вызова конструктора осуществляется неявно:

  • формальный параметр – объект, передаваемый по значению, создается в стеке в момент вызова функции и инициализируется копией фактического параметра;
  • результат функции – объект, передаваемый по значению, в момент выполнения оператора return копируется во временный объект, сохраняющий результат функции.

Во всех этих случаях транслятор не вызывает конструктора для вновь создаваемого объекта:

  • date2 в приведенном определении;
  • создаваемого в стеке формального параметра;
  • временного объекта, сохраняющего значение, возвращаемое функцией.

Вместо этого в них копируется содержимое объекта-источника:

  • date1 в приведенном примере;
  • фактического параметра;
  • объекта-результата в операторе return.
Конструктор копии

Конструктор копирования обязателен, если в программе используются функции-элементы и переопределенные операции, которые получают формальные параметры и возвращают в качестве результата такой объект не по ссылке, а по значению
При наличии в объекте указателей на динамические переменные и массивы или идентификаторов связанных ресурсов, такое копирование требует дублирования этих переменных или ресурсов в объекте-приемнике. С этой целью вводится конструктор копии, который автоматически вызывается во всех перечисленных случаях. Он имеет единственный параметр-ссылку на объект-источник:

class String {
  char *str;
  int size;
public:
  String(String&); // Конструктор копирования
};
String::String(String& right) { // Создает копии динамических
// переменных и ресурсов
  s = new char[right->size];
  strcpy(str,right->str);
}
Деструктор

Определяемый пользователем класс имеет конструктор, который обеспечивает надлежащую инициализацию. Для многих типов также требуется обратное действие. Деструктор обеспечивает соответствующую очистку объектов указанного типа. Имя деструктора представляет собой имя класса с предшествующим ему знаком "тильда" ~. Так, для класса X есть ~X(). Многие классы используют динамическую память, которая выделяется конструктором, а освобождается деструктором.

class date {
  int *day, *month, *year;
public:
  date(int d, int m, int y) {
    day = new int;
    month = new int;
    year = new int;
    *day = d;
    *month = m;
    *year = y;
   }
~date() { delete day; delete month; delete year; }
};
Член-данные, имеющие тип класса

Пусть имеется класс vect, реализующий защищенный массив, и необходимо хранить несколько значений для каждого такого массива: возраст, вес и рост группы лиц. Группируем 3 массива внутри нового класса.

#include "vect.h" // описание класса vect
class multi_v {
public:
  vect a, b, c;
  multi_v(int i): a(i), b(i), c(i){}
};

Конструктор нового класса имеет пустое тело и список вызываемых конструкторов класса vect, перечисленных после двоеточия (:) через запятую (,). Они выполняются с целым аргументом i, создавая 3 объекта класса vect: a, b, c.

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

int main() {
  multy_v dan(3);  // Вызывает 3 конструктора для класса vect
  for(int i=0; i<=dan.a.razm(); i++)
    {
     dan.a.element(i)=10+i;
     dan.b.element(i)=20+5*i;
     dan.c.element(i)=120+5*i;
    }
  for(int i=0; i<=dan.a.razm(); i++)
    {
     cout << dan.a.element(i) << "лет \t";
     cout<< dan.b.element(i) << "кг \t";
     cout << dan.c.element(i) << "см" << endl;
    }
  cin.get();
  return 0;
}

При выполнении программы перед выходом из блока main для каждого члена vect будет вызываться индивидуальный деструктор. Результат работы программы

10 лет  20 кг  120 см
11 лет  25 кг  125 см
12 лет  30 кг  130 см
Назад


Назад: Язык C++

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *