C++. Функції класу, що оголошені з константним (const) покажчиком this та непостійним (volatile) покажчиком this




Функції класу, що оголошені з константним (const) покажчиком this та непостійним (volatile) покажчиком this


Зміст


Пошук на інших ресурсах:

1. Як виглядає загальна форма оголошення функції з константним покажчиком this?

Оголошення функції у класі (на прикладі функцій MyFun1(), MyFun2()) з константним покажчиком this має такий загальний вигляд:

class CMyClass
{
    private:
    // приховані члени даних та методи класу
    // ...

    public:
    // функція оголошена з константним покажчиком this
    return_type MyFun1(parameters) const; // out-of-line
    return_type MyFun2(parameters) const // inline реалізація
    {
        // тіло функції
        // ...
    }
}

// реалізація out-of-line функції
return_type CMyClass::MyFun1(parameters) const
{
    // тіло функції MyFun1()
    // ...
}

де

  • return_type – тип, що повертається тією чи іншою функцією;
  • parameters – параметри, які отримує функція.

У вищенаведеному фрагменті, у класі CMyClass оголошуються дві функції з константним покажчиком this. Функція MyFun1() реалізована за межами класу (типу out-of-line). Функція MyFun2() реалізована в класі (типу inline). Перед тілом кожної функції стоїть ключове слово const.

⇑

2. В чому полягає суть оголошення функції з константним покажчиком this?

У функції з константним покажчиком this перед тілом функції ставиться ключове слово const. Це означає, що тіло функції має обмежені можливості використання.

Слід зауважити, що у цьому випадку ключове слово const не має відношення до значення, що повертається функцією. Воно має значення тільки для покажчика this, що використовується у функції.

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

⇑

3. Приклад, що демонструє відмінність між функціями з константним покажчиком this та без нього

Відмінність між звичайною функцією та функцією з константним покажчиком this добре видно в реалізації нижченаведеного класу.

Нехай задано клас CRadius, що реалізує радіус деякого об’єкта чи геометричної фігури. У класі реалізовано:

  • внутрішній член даних типу double;
  • конструктор CRadius();
  • звичайну функцію GetRadius(), яка збільшує радіус удвічі і повертає його значення;
  • функцію GetRadius2(), оголошену з константним покажчиком this. Дана функція повертає значення внутрішньої змінної radius.
// клас CRadius
class CRadius
{
    double radius;

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

    // Звичайна функція-член класу,
    // цій функції неявно передається покажчик: CRadius * const this
    double GetRadius(void)
    {
        radius *= 2.0; // дозволено
        return radius;
    }

    // Функція-член класу, оголошена з const
    // цій функції передається покажчик: const CRadius * const this
    double GetRadius2(void) const
    {
        //radius = 2.0; // Заборонено! Помилка компіляції
        return radius;
    }
};

Якщо у функції GetRadius2() спробувати змінити значення внутрішньої змінної radius, то вийде помилка компіляції:

Error: 'radius' cannot be modified because it is being accessed through a const object

Ключове слово const перед тілом функції в класі означає, що функції заборонено вносити будь-які зміни в члени даних класу.

Використання класу CRadius в деякому програмному коді, наприклад, обробнику події:

CRadius CR;

double d;
d = CR.GetRadius2(); // d = 1.0 - виклик функції з константним this
d = CR.GetRadius(); // d = 1.0 - виклик звичайної функції-члена

⇑

4. Яким чином модифікується покажчик this, що передається функції-члену, яка оголошена з константним покажчиком this?

Нехай задано клас CRadius, в якому є функція-член з константним покажчиком this:

// клас CRadius
class CRadius
{
    double radius;

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

    // Звичайна функція-член класу,
    // цій функції неявно передається покажчик: CRadius * const this
    double GetRadius(void)
    {
        radius *= 2.0; // дозволено
        return radius;
    }

    // Функція-член класу, оголошена з const
    // цій функції передається покажчик: const CRadius * const this
    double GetRadius2(void) const
    {
        //radius = 2.0; // Заборонено! Помилка компіляції
        return radius;
    }
};

Покажчик this у класі є невидимий, функціям класу він передається неявно. Це означає, що при спробі явного опису покажчика this у класі, компілятор видасть помилку.
Звичайній функції-члену класу GetRadius() покажчик this передається в неявному вигляді як:

CRadius * const this;

Функції-члену GetRadius2() невидимий покажчик this передається з ключовим словом const:

// модифікований покажчик this
const CRadius * const this;

Запис

const CRadius

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

⇑

5. Для чого потрібно використовувати функції класу з константним покажчиком this?

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






⇑

6. Що буде, якщо ключове слово const розмістити перед іменем функції, а не перед тілом функції?

Це є важливо. У цьому випадку, функція повертає константне значення. Але змінювати внутрішні дані класу у тілі функції можна.
Ключове слово const перед іменем функції відноситься до значення, яке повертається функцією. Ключове слово const перед тілом функції відноситься до покажчика this.

⇑

7. Чи можна оголошувати ключове слово const для статичних функцій-членів?

Оголошення статичної функції-члена з ключовим словом const не має змісту. При виклику статичної функції-члена, невидимий покажчик this не передається цій функції. При спробі оголошення статичної функції-члена з константним покажчиком this компілятор видасть помилку

... modifiers not allowed on static members functions

⇑

8. Яка загальна форма оголошення функції-члена з непостійним покажчиком this? Ключове слово volatile

Для того, щоб оголосити функцію-член з непостійним покажчиком this використовується ключове слово volatile.
Загальна форма оголошення функції з непостійним покажчиком this в класі має приблизно наступний вигляд:

class CMyClass
{
    // приховані члени даних та методи класу
    // ...

    public:
    // загальнодоступні члени даних та методи класу
    // функція-член з непостійним покажчиком this
    return_type MyFun1(parameters) volatile; // out-of-line
    return_type MyFun2(parameters) volatile // inline
    {
        // тіло функції
        // ...
    }
}

// реалізація out-of-line функції
return_type CMyClass::MyFun1 volatile
{
    // тіло функції MyFun1()
    // ...
}

де

  • return_type – тип, що повертається тією чи іншою функцією;
  • parameters – параметри, які отримує функція.

У вищенаведеному фрагменті, у класі CMyClass оголошуються дві функції з непостійним (volatile) покажчиком this. Функція MyFun1() реалізована за межами класу (типу out-of-line). Функція MyFun2() реалізована у класі (типу inline). Перед тілом кожної функції стоїть ключове слово volatile.

⇑

9. У яких випадках доцільно оголошувати функцію з непостійним (volatile) покажчиком this?

Оголошення функції як volatile доцільно використовувати у випадках, коли потрібно обробляти об’єкт класу різними процесами, до яких можна віднести:

  • обробка об’єкту процесором;
  • обробка з допомогою фонових прикладних програм;
  • обробка з допомогою програм обробки переривань.

⇑

10. Що дає використання ключового слова volatile для функції-члена класу?

Функція-член класу, що оголошена з ключовим словом volatile трактується компілятором у різних випадках по різному. Для таких функцій компілятор відключає деякі види оптимізації в залежності від типу оголошеного об’єкту.
Функції-члени класу, що оголошені з ключовим словом volatile можна використовувати як для автоматичних об’єктів так і для непостійних (volatile) об’єктів.
Для константних об’єктів використання функцій з непостійним покажчиком заборонено. Знову ж таки, все залежить від налаштувань та реалізації компілятора.

⇑

11. Приклад використання функцій-членів класу з непостійним покажчиком this

Нехай дано клас CRadius. У класі реалізовано:

  • внутрішній член-даних radius;
  • конструктор CRadius();
  • звичайну функцію-член класу GetRadius();
  • дві фунції-члени класу з непостійним покажчиком this: GetRadius2() та SetRadius().
// клас CRadius
class CRadius
{
    double radius;

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

    // Звичайна функція-член класу,
    // цій функції неявно передається CRadius * const this
    double GetRadius(void)
    {
        return radius;
    }

    // Функція-член класу, оголошена з volatile
    // цій функції передається volatile CRadius * const this
    double GetRadius2(void) volatile
    {
        return radius;
    }

    // Функція-член класу, оголошена з volatile
    void SetRadius(double r) volatile
    {
        radius = r;
    }
};

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

CRadius CR1; // автоматичний об'єкт
volatile CRadius CR2; // непостійний об'єкт

double d;

// автоматичний об'єкт
CR1.SetRadius(5.5);
d = CR1.GetRadius2(); // d = 5.5

// непостійний об'єкт
CR2.SetRadius(6.7);
d = CR2.GetRadius2(); // d = 6.7

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

⇑


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

⇑