14.8  Конструктор инициализирующий

Конструктор инициализирующий – это конструктор, который вызывается с одним или несколькими аргументами.

При использовании инициализирующего конструктора происходит инициализация переменных-членов аргументами конструктора. Если какая-то из закрытых переменных-членов осталась неинициализирована, то компилятор вызывает для нее конструктор по умолчанию, если он существует, в противном случае он выдает ошибку.

Рассмотрим простой пример, демонстрирующий использование инициализирующего конструктора:

class Stack

{

char * s; 

int max_len;

int top;

public:

Stack(int);  // Конструктор инициализирующий

// …

};

inline Stack :: Stack(int size)

{                  

s = new char[size];  

max_len = size;

top = 0;

}

Конструктор класса Stack выполняет инициализацию член-дан­ных max_len и top, а также указателя s. Указатель s инициализи­руется адресом динамической области, полученной операцией new. Размер области определяется аргументом, который принимает конструктор. Каждый раз при создании объекта типа Stack будет автоматиче­ски вызываться этот конструктор:

Stack s1(100);                         // Создание объекта с помощью конструктора

Stack * р = new Stack(50);  // Создание объекта операцией new

Если у класса есть конструктор, при определении объекта он всег­да будет вызываться, даже если он явно не указан, поэтому аргумен­ты конструктору в той или иной форме должны быть заданы:

Stack s3(512);                  // Краткая форма (неявный вызов конструктора)

Stack s4;                         // Ошибка, не задан аргумент для конструктора

Наличие конструктора в классе Stack вынуждает при определе­нии объекта этого класса указывать аргументы.

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

class Stack

{  

char * s;

int max_len;

int top;

public:

Stack(int);                 // Конструктор 1

Stack(char *, int);     // Конструктор 2 

// … 

};                    

Stack :: Stack(int size) 

{

s = new char [size];

max_len = size; 

top = 0;

}

Stack :: Stack(char * p, int size)                                     

{    

s = p;

max_len = size;  

top = 0;

}

В классе Stack определены два конструктора, что дает возмож­ность объявить объект класса Stack двумя способами:       

1) указав размер стека (конструктор Stack (int));

2) указав адрес ранее распределенной области и ее размер (конструктор Stack (char * p, int size)).

Во втором случае динамическая память для стека не будет распределяться операцией new, а будет использоваться память, ад­рес которой конструктор получит в качестве аргумента. Наличие такого конструктора – плохой стиль программирования, посколь­ку область стека напрямую доступна в программе и может там изменяться.

Динамическая память, получаемая первым конструктором, в программе напрямую недоступна: указатель s "скрыт" в части private класса Stack.

Подчеркнем, что собственно конструктор не резервирует па­мять для объекта. Он выполняет только те операции, которые запи­саны в теле функции-конструктора. Таким образом, хотя конст­руктор Stack (int) и получает область динамической памяти по опе­рации new, в результате его действия будет инициализирован лишь указатель s и установлено значение член-данных max_len и top. Память же для объекта класса Stack, как и для объектов встроен­ных типов, отводится механизмом его объявления.