С++. Конструктор копіювання. Приклади використання. Передача об’єкту класу в функцію. Повернення класу

С++. Класи. Частина 2. Конструктор копіювання. Приклади використання. Передача об’єкту класу в функцію. Повернення класу з функції

У даній темі розглянуто роботу конструктора копіювання на прикладі unmanaged (native) класів. При розгляді даної теми рекомендується прочитати тему:


Зміст



1. Що таке конструктор копіювання (copy constructor)? Приклад

Це спеціальний конструктор, що дозволяє отримати ідентичний до заданого об’єкт. Тобто, з допомогою конструктора копіювання можна отримати копію вже існуючого об’єкту. Конструктор копіювання ще називається ініціалізатором копії (copy initializer). Конструктор копіювання повинен отримувати вхідним параметром посилання (&) на об’єкт такого самого класу.

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

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

// клас CMyPoint
class CMyPoint
{
    int x, y;

    public:
    CMyPoint(void); // конструктор класу за замовчуванням
    CMyPoint(int nx, int ny); // конструктор класу з двома параметрами
    CMyPoint(CMyPoint & ref_Point); // конструктор копіювання

    // методи доступу - реалізовані в класі
    int GetX(void) { return x; }
    int GetY(void) { return y; }
};

// реалізація конструкторів (методів) класу
// конструктор класу CMyPoint
CMyPoint::CMyPoint(void)
{
    x = y = 0;
}

// конструктор класу CMyPoint з двома параметрами
CMyPoint::CMyPoint(int nx, int ny)
{
    x = nx;
    y = ny;
}

// конструктор копіювання класу CMyPoint
// передається посилання на CMyPoint
CMyPoint::CMyPoint(CMyPoint & ref_Point)
{
    // копіювання даних з одного об'єкту в інший
    x = ref_Point.x;
    y = ref_Point.y;
}

Демонстрація використання конструктора копіювання у деякому програмному коді (методі)

// демонстрація використання конструктора копіювання
CMyPoint p1(5, 8); // створення об'єкту p1
CMyPoint p2; // створення об'єкту p2 - викликається конструктор за замовчуванням

// перевірка
int d;
d = p1.GetX(); // d = 5
d = p2.GetX(); // d = 0

p2 = p1; // побітове копіювання, конструктор копіювання не викликається
d = p2.GetX(); // d = 5, дані скопіювались, але не з допомогою конструктора копіювання

// код, що викликає конструктор копіювання
CMyPoint p3 = p1; // ініціалізація об'єкта => викликається конструктор копіювання
d = p3.GetX(); // d = 5

2. У яких випадках доцільно використовувати конструктор копіювання?

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

  • створити копію об’єкту класу (дивіться попередній пункт) в момент його оголошення;
  • передати об’єкт класу у деяку функцію як параметр-значення (див. приклад нижче);
  • якщо потрібно повернути об’єкт класу за значенням (див. приклад нижче).

3. Приклад передачі об’єкту класу у функцію як параметр-значення

Приклад передачі об’єкту класу у функцію як параметр-значення. У прикладі передається об’єкт класу CMyPoint (див. п. 1) у функцію GetLength(), яка обчислює відстань від точки CMyPoint до початку координат. Текст функції наступний:

// функція, що обчислює відстань від точки до початку координат
// точка є вхідним параметром
double GetLength(CMyPoint mp)
{
    double length;
    int tx, ty;

    tx = mp.GetX();
    ty = mp.GetY();
    length = Math::Sqrt(tx*tx + ty*ty);

    return length;
}

Використання функції в іншому програмному коді

CMyPoint p1(5,5); // оголосити екземпляр класу CMyPoint
double len;

// передача точки p1 у функцію, викликається конструктор копіювання, len = 7,07...
len = GetLength(p1);

4. Приклад повернення об’єкту класу з функції за значенням з допомогою конструктора копіювання

Реалізувати функцію GetCenterPoint(), яка повертає точку, що є серединою відрізку, проведеного між точкою CMyPoint та початком координат.

Оголошення класу таке саме як у п. 1.

Реалізація двох варіантів функцій GetCenterPoint() та GetCenterPoint2().

// функція, що повертає середину відрізка
CMyPoint GetCenterPoint(CMyPoint mp)
{
    int tx, ty;
    tx = mp.GetX() / 2;
    ty = mp.GetY() / 2;

    // повернення з функції, конструктор копіювання не викликається
    // замість нього викликається конструктор з 2 параметрами
    return CMyPoint(tx, ty);
}

// функція, що повертає середину відрізка, заданого точками
CMyPoint GetCenterPoint2(int x, int y)
{
    CMyPoint mp(x/2, y/2);

    // створюється тимчасовий об'єкт, який ініціалізується значенням з mp, 
    // у результаті викликається конструктор копіювання
    return mp;

    // у цьому випадку конструктор копіювання не викликається
    //return CMyPoint(x/2,y/2);
}

Демонстрація використання функцій

CMyPoint mp(18,-8);
CMyPoint mpC;

// викликається конструктор копіювання при передачі параметру у функцію як параметру-значення
mpC = GetCenterPoint(mp); 

int cx, cy;
cx = mpC.GetX(); // cx = 9
cy = mpC.GetY(); // cy = -4

// викликається конструктор копіювання при поверненні з функції
mpC = GetCenterPoint2(-9, 13); 
cx = mpC.GetX(); // cx = -4
cy = mpC.GetY(); // cy = 6

У першому варіанті GetCenterPoint() конструктор копіювання викликається тільки при передачі параметру mp за значенням. При поверненні з функції GetCenterPoint() з допомогою оператора return, конструктор копіювання не викликається. Замість нього викликається конструктор з двома параметрами, що оголошений у класі.

У другому варіанті GetCenterPoint2() конструктор копіювання викликається при поверненні з функції оператором return. В операторі return створюється тимчасовий об’єкт класу CMyPoint, який одразу ініціалізується значенням mp, у результаті цього викликається конструктор копіювання.


Зв’язані теми