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;
:::::
}
И опять возникают новые проблемы. На этот раз они связаны с попыткой присвоения значения константе.