C++. Бархатный путь. Часть 2 - Инициализация объекта: параметры и инициализаторы

ОГЛАВЛЕНИЕ

 

Инициализация объекта: параметры и инициализаторы

Совместно используемые функции различаются списками параметров. В этом смысле конструкторы подобны функциям. Рассмотрим определение конструктора с параметрами. Мы расположим его за пределами класса. При этом в классе располагается прототип конструктора, а его имя при определении заменяется квалифицированным именем:

class ComplexType {
:::::
public:
ComplexType(double keyReal,
double keyImag,
char keyCTcharVal,
int keyX);
:::::
};
:::::
ComplexType::ComplexType(double keyReal,
double keyImag,
char keyCTcharVal,
int keyX)
{
cout << "This is ComplexType("
<< keyReal << ","
<< keyImag << ","
<< (int)keyCTcharVal << ","
<< keyX << ")" << endl;
real = keyReal;
imag = keyImag;
CTcharVal = keyCTcharVal;
x = keyX;
};

А вот и подходящее определение. Мы расположим его в функции main:

ComplexType CDw2(100,100,0,0);
/* Создаётся объект типа ComplexType под именем CDw2 с
определёнными значениями. */
int iVal(10);
/* Аналогичным образом может быть определён и проинициализирован
объект основного типа */

Заметим, что к такому же результату (но только окольными путями) приводит и такая форма оператора определения:

ComplexType CDw2 = ComplexType(100,100,0,0);

И снова мы встречаем случай определения объекта посредством постфиксного выражения. Здесь опять можно говорить о явном обращении к конструктору с передачей ему параметров. Выражения явного приведения типа здесь построить невозможно, поскольку за заключённым в скобочки именем типа должно стоять унарное выражение.

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

ComplexType CDw1(); // Это ошибка!
int xVal(); // Это тоже не определение.

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

При объявлении и определении функций C++ позволяет производить инициализацию параметров. Аналогичным образом может быть модифицирован прототип конструктора с параметрами:

ComplexType(double keyReal = 0,
double keyImag = 0,
char keyCTcharVal = 0,
int keyX = 0);

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

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

  • конструктор, автоматически создаваемый транслятором,
  • определяемый программистом конструктор с пустым списком параметров,
  • конструктор с проинициализированными по умолчанию параметрами.

Внесём ещё одно изменение в текст нашей программы. На этот раз мы добавим спецификатор const в объявление данного-члена класса x:

class ComplexType
{
:::::
const int x;
:::::
}

И опять возникают новые проблемы. На этот раз они связаны с попыткой присвоения значения константе.