C++. Класи. Види функцій-членів класу. Прості функції-члени. Статичні (static) функції-члени. Приклади використання

C++. Класи. Види функцій-членів класу. Звичайні функції-члени. Статичні (static) функції-члени. Приклади використання

Дана тема базується на використанні функцій-членів класу, орієнтованих на компілятор Visual C++. У реалізаціях компіляторів різних розробників можуть бути суттєві відмінності, особливо що стосується статичних функцій-членів.


Зміст



1. Які види функцій-членів можна оголошувати в класах?

У класах можна оголошувати такі види функцій:

  • “звичайні” функції-члени. Це функції, в оголошенні яких не використовуються додаткові ключові слова (const, volatile, static);
  • статичні функції. Це функції, які оголошені з ключовим словом static;
  • константні функції. Це функції, які оголошені з ключовим словом const;
  • функції-члени, що повертають непостійний об’єкт. Це функції, які оголошені з ключовим словом volatile;
  • функції-члени з константним покажчиком this;
  • функції-члени з непостійним покажчиком this;
  • вбудовані функції-члени (inline).

2. Приклад оголошення класу, що містить функції-члени, які не використовують додаткових ключових слів

У даному прикладі оголошено клас CLine, що описує лінію на координатній площині. Лінія складається з координат точок (x1; y1), (x2; y2). Клас містить прості функції члени, які оголошені в розділі public (загальнодоступні). З допомогою цих функцій-членів здійснюється читання/модифікація внутрішніх змінних класу.

// клас, що описує лінію на координатній площині
class CLine
{
    int x1, y1;
    int x2, y2;

    public:
    CLine(void);
    ~CLine(void);

    // методи класу
    void SetLine(int nx1, int ny1, int nx2, int ny2);
    int GetX1(void) { return x1; }
    int GetY1(void) { return y1; }
    int GetX2(void) { return x2; }
    int GetY2(void) { return y2; }
};

// Реалізація методів класу
// конструктор за замовчуванням
CLine::CLine(void)
{
    x1 = y1 = 0;
    x2 = y2 = 1;
}

// деструктор
CLine::~CLine(void)
{
}

// реалізація простої функції-члена класу
void CLine::SetLine(int nx1, int ny1, int nx2, int ny2)
{
    x1 = nx1;
    y1 = ny1;
    x2 = nx2;
    y2 = ny2;
}

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

// оголошення об'єкту класу CLine
CLine CL;
int t;

// виклик функцій-членів класу
CL.SetLine(5, 6, 10, 20);
t = CL.GetX2(); // t = 10
t = CL.GetY1(); // t = 6

3. Приклад оголошення класу, що містить статичні (static) функції-члени

У даному прикладі оголошено клас CCircle, що описує коло на координатній площині. Клас реалізує такі внутрішні члени даних та методи:

  • внутрішні змінні (члени) класу x, y, r (координати центру та радіус кола);
  • конструктор класу CCircle(), який визначає одиничне коло (r=1) з центром на початку координат;
  • статичну функцію-член класу SetData1(), яка встановлює значення глобальних змінних xx, yy, rr оголошених за межами класу;
  • звичайну (нестатичну) функцію-член класу SetData2(), яка змінює значення внутрішніх змінних x, y, r класу;
  • звичайні (нестатичні) методи класу, що читають значення внутрішніх змінних класу x, y, r та глобальних змінних xx, yy, rr.
// клас, що описує коло на координатній площині
class CCircle
{
    // внутрішні змінні класу
    int x, y; // координати центру кола
    int r; // радіус кола

    public:
    // конструктор класу
    CCircle(void);

    // статичний метод класу - тільки для глобальних змінних
    static void SetData1(int nx, int ny, int nr);

    // звичайні (нестатичні) методи класу
    // встановити нові значення внутрішніх змінних класу
    void SetData2(int nx, int ny, int nr);

    // зчитати значення внутрішніх змінних класу
    int GetX(void) { return x; }
    int GetY(void) { return y; }
    int GetR(void) { return r; }

    // зчитати значення глобальних змінних класу
    int GetXX(void);
    int GetYY(void);
    int GetRR(void);
};

// глобальні змінні
int xx, yy, rr; // ці змінні може змінювати статична функція-член класу

// конструктор класу
CCircle::CCircle(void)
{
    // заповнення значень внутрішніх (локальних) змінних
    x = 0; y = 0; r = 1;
}

// статична функція-член класу
void CCircle::SetData1(int nx, int ny, int nr)
{
    // присвоювання значень глобальним змінним,
    // що оголошені поза межами класу
    xx = nx;
    yy = ny;
    rr = nr;

    // працювати з внутрішніми змінними класу у статичній функції заборонено
    // x = nx; // Заборонено! Помилка: "... illegal reference to non-static member 'CCircle::x'
    // y = ny; // також заборонено
}

// встановити нові значення звичайних (нестатичних) методів класу
void CCircle::SetData2(int nx, int ny, int nr)
{
    x = nx;
    y = ny;
    r = nr;
}

// зчитати значення глобальних змінних класу
int CCircle::GetXX(void)
{
    return xx;
}

int CCircle::GetYY(void)
{
    return yy;
}

int CCircle::GetRR(void)
{
    return rr;
}

Змінювати значення внутрішніх змінних класу зі статичної функції-члена класу заборонено. Якщо у функції SetData1() спробувати змінити значення внутрішніх змінних класу x, y

void CCircle::SetData1(int nx, int ny, int nr)
{
    ...
    x = nx;
    y = ny;
    ...
}

то компілятор видасть помилку

 ... illegal reference to non-static member 'CCircle::x'

Якщо потрібно змінити значення внутрішніх змінних класу зі статичної функції-члена, тоді цій функції потрібно передати покажчик this класу.

Нижченаведений програмний код демонструє використання статичної функції-члена для класу Circle

// використання класу CCircle
CCircle C1;
int tx, ty, tr; // додаткові змінні

// виклик статичної функції-члена
C1.SetData1(2, 3, 4); // змінюються тільки глобальні змінні xx, yy, rr
// прочитати значення внутрішніх змінних класу
tx = C1.GetX(); // tx = 0 - внутрішні змінні x,y,r ініціалізовані конструктором класу
tr = C1.GetR(); // tr = 1

// прочитати значення глобальних змінних, що оголошені за межами класу
tx = C1.GetXX(); // tx = 2
ty = C1.GetYY(); // ty = 3

// виклик звичайної (нестатичної) функції-члена класу
C1.SetData2(2, 3, 4); // змінюються тільки внутрішні змінні x, y, r
tx = C1.GetX(); // tx = 2
tr = C1.GetR(); // tr = 4

// інший спосіб виклику статичної функції-члена
CCircle::SetData1(7, 8, 9);
tx = C1.GetXX(); // tx = 7
ty = C1.GetYY(); // ty = 8

4. Яка відмінність статичних функцій-членів від звичайних функцій-членів

Основні відмінності статичних функцій-членів від звичайних:

  • викликати статичну функцію-член можна без посилання на об’єкт класу, наприклад CMyClass::MyStaticFuntion(…). У цьому випадку використовується оператор розширення області видимості ‘::’;
  • статичні функції-члени не отримують покажчика this класу. Це означає, що вони не можуть отримати доступ до членів даних класу (за винятком членів-даних класу, які оголошені як статичні – з ключовим словом static);
  • у C++ статична функція-член класу є глобальною. Тому її доцільно використовувати для зміни значень глобальних змінних, які оголошені за межами класу але мають застосування в класі.

5. У яких випадках доцільно застосовувати статичні (static) функції-члени класу

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


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