Урок №127. Делегуючі конструктори

  Юрій  | 

  Оновл. 3 Лют 2021  | 

 59

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

Проблема

При створенні нового об’єкта класу, компілятор C++ неявно викликає конструктор цього об’єкту. Не рідкість зустріти клас з декількома конструкторами, які частково виконують одне і те ж, наприклад:

Тут є 2 конструктори: конструктор за замовчуванням і конструктор, який приймає цілочисельне значення. Оскільки Частина коду X потрібна обом конструкторам, то вона дублюється в кожному з них.

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

Рішення в C++11

Непогано було б, щоб конструктор Boo(int) викликав конструктор Boo() для виконання Частина коду X:

Або:

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

До C++11 явний виклик одного конструктора з іншого призводить до створення тимчасового об’єкта, який потім ініціалізується за допомогою конструктора цього об’єкту і ігнорується, залишаючи вихідний об’єкт незмінним.

Використання окремого методу

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

Тут ми звели дублювання коду до мінімуму.

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

Тут ми підключаємо функцію Init() для ініціалізації змінних-членів назад значеннями за замовчуванням, а потім кожен конструктор викликає функцію Init() перед своїм фактичним виконанням. Це зменшує дублювання коду до мінімуму і дозволяє явно викликати Init() з будь-якого місця в програмі.

Делегуючі конструктори

Починаючи з C++11, конструкторам дозволено викликати інші конструктори. Цей процес називається делегуванням конструкторів (або “ланцюжком конструкторів”). Щоб один конструктор викликав інший, потрібно просто зробити виклик цього конструктора в списку ініціалізації членів. Наприклад:

Все працює як потрібно. Переконайтеся, що ви викликаєте конструктор зі списку ініціалізації членів, а не з тіла конструктора.

Ось ще один приклад використання делегуючих конструкторів для зменшення дубльованого коду:

Цей клас має 2 конструктори (один з яких викликає іншого). Таким чином, кількість дубльованого коду зменшено (нам потрібно записати тільки одне визначення конструктора замість двох).

Декілька заміток про делегуючі конструктори

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

По-друге, один конструктор може викликати іншого конструктора, в коді якого може знаходитися виклик першого конструктора. Це створить нескінченний цикл і призведе до того, що пам’ять стеку закінчиться і відбудеться збій. Ви можете уникнути цього, переконавшись, що в конструкторі, який викликається, немає виклику першого (і взагалі будь-якого іншого) конструктора. Будьте обережні і не використовуйте вкладені виклики конструкторів.

Оцінити статтю:

1 Зірка2 Зірки3 Зірки4 Зірки5 Зірок (2 оцінок, середня: 5,00 з 5)
Loading...

Залишити відповідь

Ваш E-mail не буде опублікований. Обов'язкові поля відмічені *