Посилання на об’єкт класу. Доступ до об’єкту класу за посиланням. Посилання як члени даних класу. Приклади

Посилання на об’єкт класу. Доступ до об’єкту класу за посиланням. Посилання як члени даних класу. Приклади


Зміст



1. Як оголошується змінна, що є посиланням на клас? Як оголосити посилання на об’єкт класу?

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

Загальний вигляд оголошення посилання на об’єкт класу має вигляд:

CMyClass & ref = obj;

де

  • CMyClass – ім’я класу;
  • ref – ім’я змінної, яка є посиланням на об’єкт obj;
  • obj – ім’я об’єкту, для якого виділена пам’ять.

2. Приклад оголошення посилання на об’єкт класу та його використання

Нехай задано клас CYear, що реалізує рік. Оголошення класу має такий вигляд:

// клас, що реалізує категорію "Рік"
class CYear
{
    int year; // внутрішня змінна

    public:
    CYear(void); // конструктор за замовчуванням

    // конструктор з 1 параметром
    CYear(int year)
    {
        this->year = year;
    }

    // методи доступу
    int Get(void) { return year; }
    void Set(int year) { this->year = year; }

    // метод, що визначає чи високосний рік
    bool IsLeapYear(void);
};

// конструктор за замовчуванням
CYear::CYear(void)
{
    year = 2000; // початкова ініціалізація
}

// метод, що визначає чи високосний рік
bool CYear::IsLeapYear(void)
{
    if ((year % 4) == 0) return true;
    else return false;
}

Використання класу в іншому методі

CYear c1; // c1 - об'єкт
CYear & c2 = c1; // c1 і c2 вказують на одну й туж ділянку пам'яті

int d;

// доступ до об'єкту c1
c1.Set(2010); 
d = c1.Get(); // d = 2010

// доступ через посилання c2
d = c2.Get(); // d = 2010
c2.Set(3333);
d = c1.Get(); // d = 3333; c1 і c2 вказують на ту саму ділянку пам'яті

У вищенаведеному коді з допомогою символу & оголошується змінна-посилання c2 на об’єкт класу c1 з допомогою рядка

CYear & c2 = c1;

Для змінної c1 пам’ять вже виділена. Змінні c1 і c2 посилаються на одну й туж ділянку пам’яті (на той самий об’єкт).

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

Якщо оголосити покажчик на клас (*) і виділити для нього пам’ять, то на цю ділянку пам’яті (об’єкт) можна оголосити посилання.
Нижченаведений приклад демонструє використання покажчика та посилання на клас CYear, що описується в п. 2.

CYear * pc = new CYear(); // некерований покажчик, виділяється пам'ять
CYear & rc = (*pc); // посилання на пам'ять, виділену для покажчика

int d;

// доступ до об'єкту за покажчиком
pc->Set(2040);
d = pc->Get(); // d = 2040
d = rc.Get(); // d = 2040
rc.Set(2100);
d = pc->Get(); // d = 2100

4. Приклад використання посилання на об’єкт класу, яке є членом даних іншого класу. Що відбудеться, якщо в класі не ініціалізувати посилання на об’єкт?

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

У прикладі нижче демонструється застосування класу CLine (відрізок), в якому оголошуються два посилання на клас CPoint, що описує точку.

У класі CPoint реалізовано такі члени даних та методи:

  • внутрішні змінні x, y – координати точки;
  • конструктор за замовчуванням;
  • методи доступу GetXY(), SetXY().

У класі CLine оголошуються такі члени даних та методи:

  • внутрішні змінні-посилання типу CPoint& (посилання на об’єкт класу CPoint) з іменами p1, p2;
  • конструктор з двома параметрами, що динамічно ініціалізує посилання p1, p2 при оголошенні об’єкту класу;
  • методи доступу GetPoints(), SetPoints().

Оголошення класів CPoint та CLine має вигляд:

// клас, що реалізує точку
class CPoint
{
    int x,y;

    public:
    // конструктор за замовчуванням
    CPoint() { x = y = 0; }

    // методи доступу
    void GetXY(int* nx, int* ny)
    {
        *nx = x;
        *ny = y;
    }

    void SetXY(int nx, int ny)
    {
        x = nx;
        y = ny;
    }
};

// клас, що реалізує відрізок
class CLine
{
    // посилання на об'єкти типу CPoint
    CPoint & p1;
    CPoint & p2;

    public:

    // конструктор за замовчуванням
    // динамічно ініціалізуються значення посилань p1 та p2
    CLine():p1(* new CPoint), p2(* new CPoint)
    {
        p1.SetXY(0, 0);
        p2.SetXY(1, 1);
    }

    // методи доступу
    // повернути координати точок
    void GetPoints(CPoint* pt1, CPoint* pt2)
    {
        int x, y;
        p1.GetXY(&x, &y); // взяти значення x, y для точки p1
        pt1->SetXY(x, y); // встановити x,y в нову точку pt1

        p2.GetXY(&x, &y); // взяти x,y
        pt2->SetXY(x, y); // записати x,y в pt2
    }

    // встановити нові значення точок
    void SetPoints(CPoint* pt1, CPoint* pt2)
    {
        int x, y;

        // p1 => pt1
        p1.GetXY(&x, &y);
        pt1->SetXY(x, y);

        // p2 => pt2
        p2.GetXY(&x, &y);
        pt2->SetXY(x, y);
    }
};

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

p1' : must be initialized in constructor base/member initializer list ...

У класі CLine здійснюється динамічна ініціалізація посилань p1 та p2 з допомогою конструктора:

// динамічна ініціалізація змінних-посилань p1, p2 класу CLine
CLine():p1(* new CPoint), p2(* new CPoint)
{
    // ...
}

Використання класу CLine в іншому методі:

// посилання на об'єкти як члени-даних класу
CLine cl1; // викликається конструктор, який ініціалізує змінні-посилання p1, p2

// додаткові змінні
CPoint point1, point2;
int x, y;

// перевірка, як конструктор заповнив коодинати точок відрізка
cl1.GetPoints(&point1, &point2);
point1.GetXY(&x, &y); // x = 0; y = 0
point2.GetXY(&x, &y); // x = 1; y = 1

// встановити нові значення
point1.SetXY(3, 8); // записати точку (3; 8)
point2.SetXY(5, 9); // записати точку (5; 9)

cl1.SetPoints(&point1, &point2);

// перевірка
CPoint pp1, pp2;
cl1.GetPoints(&pp1, &pp2);
pp1.GetXY(&x, &y); // x = 3; y = 8
pp2.GetXY(&x, &y); // x = 5; y = 9


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