Конструктори за умовчанням

Конструктор без аргументів називають конструктором за умовчанням. Такий конструктор звичайно ініціалізує змінні-члени, присвоюючи їм стандартні, встановлювані за умовчанням значення. Наприклад, наступний варіант класу CFrame має конструктор за умовчанням, що ініціалізує всі дані значенням 0:

 

class CFrame

{

private:

int Left;

int Top;

int Right;

int Bottom;

public:

CFrame ()

{

Left = Top = Right = Bottom = 0;

}

// визначення інших функцій-членів

};

 

Конструктор з одним або більше аргументами, що мають значення за умовчанням, також вважається конструктором за умовчанням, тому що його можна викликати без передачі аргументів.

Якщо конструктор для якого-небудь класу не оголошений, то компілятор генерує для цього класу конструктор за умовчанням. Такі конструктори, згенеровані компілятором, не присвоюють початкові значення змінним-членам класу. Тому, якщо необхідно однозначно ініціалізувати змінні-члени або виконати будь-які інші завдання ініціалізації, потрібно оголосити і визначити власний конструктор.

Якщо клас має конструктор за умовчанням (явно оголошений або згенерований компілятором), можна оголосити об'єкт класу без передачі аргументів, наприклад:

 

CFrame Frm;

При цьому потрібно врахувати, що якщо аргументи не передаються конструктору, в оголошення об'єкту не потрібно включати порожні круглі дужки. Якщо в таке оголошення включити круглі дужки, замість оголошення об'єкту класу вийде оголошення функції, що повертає об'єкт класу, а це не те, що потрібно. Наприклад:

 

CFrame Frm(); // оголошення функції, в якій немає

// аргументів і яка повертає

// об'єкт класу CFrame

Якщо допустити таку помилку, компілятор не згенерує повідомлення про помилку до тих пір, поки не зустрінеться інструкція, що намагається використати Frm як об'єкт класу CFrame.

7.1.4.2 Перевантажені конструктори

Аналогічно перевантаженню функцій, описаному раніше, можна також перевантажувати конструктор класу або будь-яку іншу функцію-член| класу, за винятком деструктора. Деструктори класів, робота з якими буде описана нижче, не можна перевантажувати через відсутність у них аргументів.

Перевантажені конструктори достатньо поширені. Вони надають альтернативні способи ініціалізації новостворюваного об'єкту класу. Наприклад, наступне оголошення класу CFrame містить перевантажені конструктори, які дозволяють задавати початкові значення змінним-членам класу або просто приймати значення за умовчанням як початкові:

 

class CFrame

{

private:

int Left;

int Top;

int Right;

int Bottom;

public:

// конструктор за умовчанням

CFrame ()

{

Left = Top = Right = Bottom = 0;

}

// конструктор з аргументами

CFrame (int L, int T, int R, int B)

{

SetCoord (L, T, R, B);

}

// визначення інших функцій-членів

};

 

Наступний фрагмент демонструє використання перевантаженого конструктора CFrame:

 

void main ()

{

// створення об'єкту з використанням конструктора за умовчанням

CFrame Frml;

// створення об'єкту із завданням початкових значень

CFrame Frm2 (25, 25, 100, 100);

// …

}

 

При явному оголошенні хоч би одного конструктора класу компілятор не створює конструктор за умовчанням. Отже, якщо в класі оголошений один або більше конструкторів, але серед них немає конструктора за умовчанням, клас не матиме такого.

7.1.4.3 Списки ініціалізації

При оголошенні класу забороняється ініціалізувати змінні-члени. Так, наступне оголошення класу містить помилки:

 

class C

{

private:

int N = 0; // помилка

const int CInt = 5; // помилка

int &RInt = N; // помилка

};

 

Ініціалізація змінних усередині оголошення класу безглузда, тому що оголошення класу задає всього лише тип кожної зі змінних-членів, але не резервує для них реальну область пам'яті.

Швидше за все, при написанні програми потрібно ініціалізувати змінні-члени кожного разу при оголошенні об'єкту класу. Отже, доцільно ініціалізувати змінні всередині конструктора класу.

Конструктор класу CFrame ініціалізував змінні-члени, використовуючи оператор присвоювання. Проте певним типам даних, зокрема, константам та посиланням, значення таким чином присвоєні бути не можуть. Щоб ця проблема не виникала, в мові C++ передбачена спеціальна властивість конструктора, звана списком ініціалізації, який дозволяє ініціалізувати одну або більше змінних, а не присвоювати їм значення.

Список ініціалізації в оголошенні конструктора поміщається безпосередньо після списку аргументів. Він містить двокрапку з подальшим одним або декількома ініціалізаторами полів, відокремленими один від одного комою.

Ініціалізатор поля містить ім'я змінної з подальшим початковим значенням у круглих дужках.

Наприклад, у приведеному нижче класі конструктор містить список ініціалізації, який, у свою чергу, містить ініціалізатори полів для всіх змінних класу:

 

class C

{

private:

int N;

const int CInt;

int &RInt;

public:

C (int Parm): N(Parm), CInt (5), RInt (N)

{

// код конструктора ...

}

// …

};

 

Для демонстрації можливостей списків ініціалізації створимо об'єкт, у якому змінні N та CInt ініціалізуються значеннями 0 та 5, а змінна-член RInt - як посилання на змінну N:

 

C Ob(0);