Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
+ООП_Навч_посібник.doc
Скачиваний:
7
Добавлен:
01.07.2025
Размер:
6.58 Mб
Скачать

13.7. Створення і використання конструктора копії

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

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

Аналогічна ситуація виникає під час повернення об'єкта з функції. Компілятор генерує тимчасовий об'єкт, який зберігатиме копію значення, що повертається функцією1. Цей тимчасовий об'єкт виходить за межі області видимості відразу ж, як тільки ініціатору виклику цієї функції буде повернуте "обіцяне" значення, після чого негайно викликається деструктор тимчасового об'єкта. Але, якщо цей деструктор зруйнує що-небудь потрібне для виконуваного далі коду програми, то наслідки будуть непоправні.

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

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

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

  • один об'єкт безпосередньо ініціалізував інший об'єкт, як, наприклад, в оголошенні;

  • копія об'єкта передається параметру функції;

  • генерується тимчасовий об'єкт (найчастіше як значення, що повертається функцією).

Конструктор копії застосовується тільки для ініціалізацій одного об'єкта іншим. Він не застосовується до присвоєнь.

Ось як виглядає найпоширеніший формат конструктора копії.

ім'я_класу (const ім'я_класу &obj)

{

// Тіло конструктора

}

У цьому записі елемент obj означає посилання на об'єкт, який використовують для ініціалізації іншого об'єкта. Наприклад, припустимо, у нас є клас myClass і об'єкт Y_ob типу myClass. Тоді у процесі виконання таких настанов буде викликаний конструктор копії класу myClass:

myClass X_ob = Y_ob; // Об'єкт Y_ob безпосередньо ініціалізував об'єкт X_ob.

fun_с1(Y_ob); // Об'єкт Y_ob передається як аргумент

Y_ob = fun_c2(); // Об'єкт Y_ob приймає об'єкт що повертається функцією.

У перших двох випадках конструктору копії буде передано посилання на об'єкт y, а в третьому – посилання на об'єкт, який повертається функцією fun_c2().

Варто знати! Конструктори копії не роблять ніякого впливу на операції присвоєння.

Щоб глибше зрозуміти призначення конструкторів копії, розглянемо грунтовніше їх значення у кожній з цих трьох ситуацій.