Ссылки на объект класса. Доступ к объекту класса по ссылке. Ссылки как члены данных класса. Примеры

Ссылки на объект класса. Доступ к объекту класса по ссылке. Ссылки как члены данных класса. Примеры


Содержание



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


Связанные темы