C++. Класи. Частина 3. Використання членів даних класу. Статичні члени даних в класі. Статичні члени даних для native-класів та managed-класів в середовищі CLR

C++. Класи. Частина 3. Використання членів даних класу. Статичні (static) члени даних в класі. Статичні члени даних для native-класів та managed-класів в середовищі CLR


Зміст



1. Які види доступу можуть застосовуватись до даних?

Дані і методи класу є членами класу. Під час оголошення даних можна застосовувати усі відомі способи доступу. Дані можуть бути оголошені як: приватні (private), захищені (protected), загальнодоступні (public).

Більш детально про види доступу описується в темі:

2. Чи можна ініціалізувати дані всередині класу при їх оголошенні?

Під час оголошення дані ініціалізувати не можна. Ініціалізувати дані можна в методах класу, конструкторах класу, зовнішніх методах тощо. Клас – це не об‘єкт, і пам‘ять під нього не виділяється до тих пір, поки не буде створено екземпляру (об‘єкту) класу.

Дані в класі подібні полям структури.

3. Як оголосити статичний член даних в native-класі? Приклад оголошення та використання

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

Щоб використовувати статичний член даних у класі, потрібно:

  • оголосити статичний член даних у тілі класу (у будь-якому розділі класу);
  • визначити статичний член даних за межами класу.

Приклад. У native-класі (unmanaged-класі) CMyClass оголошується статичний член даних з іменем d цілого типу.

// оголошення native-класу
class CMyClass
{
    static int d; // статичний член даних - тільки оголошення

    public:
    CMyClass(void); // конструктор
    ~CMyClass(void); // деструктор

    // методи доступу до статичного члена даних
    int Get(void) { return d; }
    void Set(int nd) { d = nd; }
};

// визначення статичного члена даних за межами класу
int CMyClass::d; // виділяється пам’ять

// явно заданий конструктор за замовчуванням
CMyClass::CMyClass(void)
{
    d = 0;
}

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

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

Використання статичного члена d, оголошеного в класі CMyClass з іншого методу (програмного коду):

// використання статичного члена класу
CMyClass MC1; // об'єкт (екземпляр) класу 1
CMyClass MC2; // об'єкт (екземпляр) класу 2

MC2.Set(25);
int t;
t = MC1.Get(); // t = 25 - обидва об'єкти мають доступ до однієї і тієї ділянки пам'яті

4. Яке правило діє щодо використання статичного члену класу екземплярами цього класу?

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

5. В якій області пам’яті розподіляється статичний член даних?

Статичний член даних розподіляється у фіксованій області даних. Це відбувається на стадії компоновки.

6. Скільки разів виділяється пам’ять для статичного члена даних?

Пам’ять для статичного члена даних виділяється на стадії компоновки тільки один раз в той момент, коли визначається статичний елемент. У прикладі вище (п. 3) пам’ять виділяється у рядку

int CMyClass::d;

7. Чи можна ініціалізувати статичний член класу при його оголошенні в native-класі?

Так, можна. Ініціалізація статичного члена даних класу здійснюється при його оголошенні. Наприклад:

int CMyClass::d = 10; // ініціалізація статичного члена даних

8. Як оголосити статичний член даних в managed-класі? Приклад оголошення та використання

На відміну від native-класів, у managed-класах оголошення статичного члена даних здійснюється як автоматичного (без додаткового визначення члену даних). Обов’язково потрібно задати ключове слово static.

Так само, як і в native-класах, у managed-класах екземпляри (об’єкти) класу мають доступ до однієї (тільки до однієї) ділянки фіксованої пам’яті.

Приклад. Нехай дано клас CMyRefClass, який оголошено як managed (керований, з ключовим словом ref). Такі класи використовуються в середовищі CLR.

// оголошення managed-класу
ref class CMyRefClass
{
    private:
    static int rd; // оголошення статичного члена в класі - тільки один раз

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

    // методи класу
    int Get(void) { return rd; }
    void Set(int nrd) { rd = nrd; }
};

// визначення статичного члена - не потрібно!
//int CMyRefClass::rd;

// конструктор класу
CMyRefClass::CMyRefClass(void)
{
    rd = 0;
}

Як видно з вищенаведеного коду, для managed-класу не потрібно окремо визначати статичний член.

Використання даного класу з іншого методу (програмного коду):

// статичні члени даних у managed-класах
CMyRefClass RC1;
CMyRefClass RC2;
CMyRefClass ^RC3 = gcnew CMyRefClass(); // managed-покажчик на клас

RC2.Set(5);

int t;
t = RC1.Get(); // t = 5

RC3->Set(15);
t = RC2.Get(); // t = 15

RC1.Set(-20);
t = RC3->Get(); // t = -20

Як видно з вищенаведеного коду, статичні члени даних у всіх класах є спільними для екземплярів цих класів, навіть якщо для екземпляру класу виділена пам’ять з допомогою оператора gcnew.

9. Які є способи доступу до загальнодоступних (public) статичних членів даних?

Якщо статичний член даних оголошений у розділі public, то доступ до нього можна отримати одним з трьох способів:

  • з допомогою символу ‘ . ‘ (крапка), якщо оголошено об’єкт (екземпляру) класу;
  • з допомогою послідовності символів ‘->’, якщо оголошено покажчик на об’єкт класу;
  • з допомогою імені класу та символів ‘::’ (розширення області видимості). Цей спосіб працює також і для статичний членів даних, оголошених в розділах private та protected.

10. Приклад використання загальнодоступного статичного члена для native-класу

Нехай задано native-клас CMyClass, в якому оголошено загальнодоступний статичний член. У програмному коді нижче продемонстровано способи доступу до загальнодоступного статичного члена класу.

// native-клас
class CMyPublicClass
{
    public:
    CMyPublicClass(void);
    ~CMyPublicClass(void);

    static int d; // загальнодоступний статичний член класу

    // методи класу
    int Get() { return d; }
    void Set(int nd) { d = nd; }
};

// визначення статичного члена класу
int CMyPublicClass::d;

// конструктор
CMyPublicClass::CMyPublicClass(void)
{
    d = 0;
}

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

Демонстрація доступу до статичного члена класу з іншого програмного коду

// демонстрація доступу до загальнодоступного статичного члена класу
CMyPublicClass PC1;
CMyPublicClass * PC2 = new CMyPublicClass(); // покажчик на клас
int t;

// доступ з допомогою символу '.'
PC1.d = 30;
t = PC1.Get(); // t = 30

// доступ з допомогою покажчика
PC2->d = 50;
t = PC2->Get(); // t = 50
t = PC1.Get(); // t = 50

// доступ з допомогою оператора розширення області видимості ::
CMyPublicClass::d = -33;
t = PC2->d; // t = -33
t = PC1.d; // t = -33

11. Приклад використання загальнодоступного статичного члена для managed-класу

Для managed-класу доступ до статичного члена класу такий самий як і для native-класу. Нехай задано оголошення managed-класу CMyPublicClass.

// managed-клас (з ідентифікатором ref)
ref class CMyPublicClass
{
    public:
    CMyPublicClass(void);
    ~CMyPublicClass(void);

    static int d; // загальнодоступний статичний член класу

    // методи класу
    int Get() { return d; }
    void Set(int nd) { d = nd; }
};

// конструктор
CMyPublicClass::CMyPublicClass(void)
{
    d = 0;
}

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

Демонстрація різних видів доступу

// демонстрація доступу до загальнодоступного статичного члена класу
CMyPublicClass PC1;
CMyPublicClass ^ PC2 = gcnew CMyPublicClass(); // managed-покажчик на клас
int t;

// доступ з допомогою символу '.'
PC1.d = 30;
t = PC1.Get(); // t = 30

// доступ з допомогою покажчика
PC2->d = 50;
t = PC2->Get(); // t = 50
t = PC1.Get(); // t = 50

// доступ з допомогою оператора розширення області видимості ::
CMyPublicClass::d = -33;
t = PC2->d; // t = -33
t = PC1.d; // t = -33

12. Для чого потрібні статичні члени даних? Переваги використання статичних членів даних

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

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

13. Які є способи доступу до прихованих статичних членів класу (оголошених в розділі private)?

Якщо статичний член класу оголошений в розділі private, то доступ до нього можна отримати одним з трьох способів:

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

Якщо для доступу до прихованого статичного члена даних використати оператор . або доступ за покажчиком ->, то компілятор видасть помилку.


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