Конструктором по умолчанию (в англ. языке используется термин default constructor) является конструктор, который может вызываться без аргументов.
Если в исходном коде класса пользователь не создал ни одного конструктора, то компилятор сам создает конструктор по умолчанию неявным способом. Однако если пользователь создал хотя бы один конструктор в классе, компилятор создавать конструктор по умолчанию не будет. Рассмотрим пример класса Stack с конструктором по умолчанию, созданным пользователем:
class Stack
{
char * s;
int max_len;
int top;
public:
Stack(); // Конструктор по умолчанию
// …
};
inline Stack :: Stack()
{
s = " ";
max_len = 0;
top = 0;
}
Или, с использованием списка инициализации можно записать:
inline Stack :: Stack() : s(" "), max_len(0), top(0) { }
Как видно из примера, закрытые переменные-члены проинициализированы по умолчанию нулем.
В языке C++, если поле экземпляра класса явным образом не инициализировано в списке, то вызывается конструктор по умолчанию для инициализации этого поля. Если такой тип не имеет конструктора по умолчанию, то это считается ошибкой.
В конструкторах удобно задавать значения параметров по умолчанию. Это упрощает использование конструкторов. Значение параметров по умолчанию можно указать или при объявлении конструктора, или в его определении. Все параметры по умолчанию должны стоять последними. Например, можно указать размер стека по умолчанию для конструктора класса Stack:
Stack :: Stack(int size = 512)
{
s = new char [size];
max_len = size;
top = 0;
}
Если для инициализации объектов класса Stack планируется использование конструктора по умолчанию, то в определении класса Stack конструктор по умолчанию должен быть только один: или Stack(), или Stack (int size =512).
Ничего особенного в определении конструктора как функции нет. Отличие от остальных член-функций заключается только в том, что конструктор может вызываться неявно для каждого объекта класса, определенного пользователем, и не имеет явно указанного возвращаемого значения.
Предположим, что в определении класса Stack содержится конструктор по умолчанию Stack(). Конструктор по умолчанию вызывается, например, при объявлении объекта:
Stack st; // Вызывается конструктор Stack()
Stack st = Stack(); // Вызывается конструктор Stack()
Stack st(); // Неправильно
Форма вызова в последнем примере неправильна, поскольку использование st() равносильно объявлению прототипа функции st, у которой нет аргументов и которая возвращает объект класса Stack.
Синтаксис объявления конструктора не содержит типа возвращаемого значения. Фактически конструктор значение возвращает, но неявно. Конструктор всегда возвращает значение указателя this на текущий объект, и нет необходимости объявлять это явно. С каждым объектом связан неявный указатель this. Он передается как неявный аргумент при вызове член-функции. Можно определить, для какого объекта вызывается конструктор: или для создаваемого посредством объявления, или создаваемого через операцию new. В случае создания объекта операцией new, указатель this при входе в функцию-конструктор равен нулю, в противном случае – указывает на уже созданный объект.
На конструктор, как и на любую другую член-функцию, распространяются правила видимости private и public. Если конструктор описан в части private, воспользоваться им можно только при создании объекта член-функциями класса. Например:
class Stack
{
private:
Stack(int);
// …
};
Stack s1(200); // Неправильно (Stack(int) "не виден" и им нельзя воспользоваться)
Stack s2; // Правильно (объект создается без использования конструктора)
Поскольку конструктор Stack (int) описан в части private, проинициализировать объект при объявлении в программе нельзя: конструктор " не виден ".
В классе может быть определено несколько конструкторов, которые заданы в различных частях private и public. В этом случае проинициализировать объект можно только "видимыми" в данный момент конструкторами. Для член-функций класса видны все конструкторы этого класса.