Конструктор (constructor, ctor) класса используется для инициализации объектов этого класса при их создании. Обычно это означает присваивание начальных значений полям класса и выделение для них памяти, если в качестве полей используются динамические массивы или подобные им типы данных.
Конструктор представляет собой специальную функцию, которая не возвращает значения, а её имя совпадает с именем класса. Т.е. в общем виде конструктор объявляется следующим образом:
имя_класса(параметры_конструктора) {
тело_конструктора;
}
Например, класс для работы с комплексными числами, которые, как известно, состоят из действительной и мнимой частей.
Здесь конструктор класса принимает 2 параметра – real и imag, но оба они являются необязательными, т.к. объявлены со значениями по умолчанию.
Обратите внимание на то, как записывается значение в поле real.
this->real = real;
Здесь real – аргумент функции (конструктора). И он перекрывает собой поле класса с таким же названием. Чтобы получить доступ к полю приходится использовать конструкцию с ключевым словом this.
Ключевое слово this в методах класса означает указатель на тот объект, который вызвал данный метод. Поэтому в данном случае this указывает на объект, который инициализируется конструктором. Т.к. this является указателем на объект, то для доступа к членам этого объекта сначала нужно произвести разыменование, т.е. написать
(*this).член_класса
Скобки необходимы потому, что операция "." имеет больший приоритет, чем операция "*", а необходимо сначала разыменовать указатель и лишь потом получить доступ к полю объекта. Поскольку указатели на классы в С++ используются очень часто, а постоянно записывать конструкции вида "(* )." неудобно, то на замену им была добавлена операция "->". Она аналогична последовательности операций "(*указатель).". Именно эта операция используется для доступа к полю real через указатель на объект this.
Метод add реализует сложение комплексного числа с другим комплексным числом, которое передаётся через аргумент метода.
Метод display выводит число на экран в удобном для просмотра виде.
Конструктор вызывается каждый раз при создании объекта класса. Если конструктор может быть вызван без параметров, то он называется конструктором по умолчанию и объекты можно объявлять как обычные переменные, т.е.
Complex number;
Класс complex имеет конструктор, который может не принимать аргументов, потому такая запись корректна. При этом будут использованы значения аргументов по умолчанию – 1 для поля real и 0 для поля imaginary.
Если же конструктор требует обязательного наличия параметров, то его вызов нужно указывать явно. Это можно сделать двумя способами, которые в большинстве случаев эквивалентны:
Complex number = Complex(2.12, 3,1);
Complex number(2.12, 3,1);
Конструктор обязан быть у каждого класса. Поэтому если программист не описал его явно, то компилятор сгенерирует автоматический конструктор – без аргументов и с пустым телом, не выполняющий никаких действий.
Пример использования разработанного класса complex:
void main()
{
setlocale(LC_ALL, "Russian");
Complex c1; // complex(1,0)
double re, im;
cout << "Введите действительную и мнимую части комплексного числа\n";
cin >> re >> im;
Complex c2(re, im);
cout << "\nЧисло 1: ";
c1.display();
cout << "\nЧисло 2: ";
c2.display();
c1.add(c2);
cout << "\nИх сумма: ";
c1.display();
cout << endl;
system("pause");
}
В этой программе создаются 2 объекта класса Complex – c1 и c2. Для каждого из них вызывается конструктор. Для c1 это конструктор с аргументами по умолчанию – 1 и 0. Для c2 – конструктор с аргументами, введёнными пользователем.
Как и в случае с методами, можно создавать множество перегруженных конструкторов в одном классе. Они будут различаться количеством и типами аргументов. Это предоставляет возможность инициализировать объект различными способами.
В конструкторах можно использовать списки инициализации, позволяющие задавать начальные значения полям класса. Список инициализации указывается через двоеточие после заголовка конструктора перед его телом:
class Film
{
public:
char name[200]; // Название фильма
unsigned short year; // Год выпуска
string director; // Режиссер
char** actors; // Актеры
// Конструктор
Film(const char* name_, unsigned short year_)
// список инициализации
: year(year_), director("unknown"), actors(NULL)
{
strcpy(name, name_);
};
};
Каждый элемент списка инициализации представляет собой поле класса и присваиваемое ему значение, которое указывается в скобках. Нужно понимать, что таким образом можно инициализировать не все поля класса. Например, поле name представляет собой массив символов, и присвоить в него другой массив (name_) невозможно, поэтому такое поле необходимо инициализировать явно в теле конструктора.
Зато в список инициализации можно поместить поля-классы, имеющие подходящие конструкторы. Например, стандартный класс string имеет конструктор, принимающий на вход массив символов. Поэтому поле director можно указать в списке инициализации со строкой "unknown". Для таких полей, которые были созданы в списке инициализации, гарантируется их уничтожение при уничтожении самого объекта, т.е. в его деструкторе.