Урок №122. Специфікатори доступу public і private

  Юрій  | 

  Оновл. 1 Лют 2021  | 

 260

На цьому уроці ми розглянемо, що таке специфікатори доступу в мові С++, які вони бувають і як їх використовувати.

Специфікатори доступу

Розглянемо наступну програму:

Тут ми оголошуємо структуру DateStruct, а потім напряму звертаємося до її членів для їх ініціалізації. Це працює, тому що всі члени структури є відкритими за замовчуванням. Відкриті члени (або “public-члени”) — це члени структури або класу, до яких можна отримати доступ ззовні цієї ж структури або класу. У вищенаведеній програмі функція main() знаходиться поза структурою, але вона може безпосередньо звертатися до членів day, month і year, так як вони є відкритими.

З іншої сторони, розглянемо наступний майже ідентичний клас:

Вам би не вдалося скомпілювати цю програму, так як всі члени класу є закритими за замовчуванням. Закриті члени (або “private-члени”) — це члени класу, доступ до яких мають лише інші члени цього ж класу. Оскільки функція main() не є членом DateClass, то вона і не має доступ до закритих членів об’єкта date.

Хоча члени класу є закритими за замовчуванням, ми можемо зробити їх відкритими, використовуючи ключове слово public:

Оскільки тепер члени класу DateClass є відкритими, то до них можна отримати доступ безпосередньо з функції main().

Ключове слово public разом з двокрапкою називається специфікатором доступу. Специфікатор доступу визначає, хто має доступ до членів цього специфікатору. Кожен з членів «набуває» рівень доступу відповідно до специфікатора доступу (або, якщо він не вказаний, відповідно до специфікатора доступу за замовчуванням).

У мові C++ є 3 рівня доступу:

   специфікатор public робить члени відкритими;

   специфікатор private робить члени закритими;

   специфікатор protected відкриває доступ до членів тільки для дружніх і дочірніх класів (детально про це на відповідному уроці).

Використання специфікаторів доступу

Класи можуть використовувати (і активно використовують) відразу кілька специфікаторів доступу для встановлення рівнів доступу для кожного зі своїх членів. Зазвичай змінні-члени є закритими, а методи — відкритими. Чому саме так? Про це ми поговоримо на наступному уроці.

Правило: Встановлюйте специфікатор доступу private змінним-членам класу і специфікатор доступу public — методам класу (якщо у вас немає вагомих підстав робити інакше).

Розглянемо приклад класу, який використовує специфікатори доступу private і public:

Результат виконання програми:

12/11/2018

Зверніть увагу, хоч ми і не можемо отримати доступ до змінних-членів об’єкта date безпосередньо з main() (так як вони є private за замовчуванням), ми можемо отримати доступ до них через відкриті методи setDate() і print()!

Відкриті члени класів складають відкритий (або “public”) інтерфейс. Оскільки доступ до відкритих членів класу може здійснюватися ззовні класу, то відкритий інтерфейс і визначає, як програми, які використовують клас, будуть взаємодіяти з цим же класом.

Деякі програмісти вважають за краще спочатку перерахувати private-члени, а потім вже public-члени. Вони керуються наступною логікою: public-члени зазвичай використовують private-члени (ті ж змінні-члени в методах класу), тому є сенс спочатку визначити private-члени, а потім вже public-члени. Інші ж програмісти вважають, що спочатку потрібно вказувати public-члени. Тут вже логіка заключається в тому, що оскільки private-члени закриті і отримати до них доступ напряму не можна, то і виносити їх на перше місце теж не потрібно. Працювати буде і так, і так. Який спосіб використовувати — вибирайте самі, що вам зручніше.

Розглянемо наступну програму:

Один нюанс в мові C++, який часто ігнорують/забувають/неправильно розуміють, полягає в тому, що контроль доступу працює на основі класу, а не на основі об’єкта. Це означає, що коли метод має доступ до закритих членів класу, він може звертатися до закритих членів будь-якого об’єкта цього класу.

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

Це корисно, коли потрібно скопіювати елементи з одного об’єкта класу в інший об’єкт того ж класу. Детально про це ми поговоримо на наступних уроках.

Структури vs. Класи

Тепер, коли ми дізналися про специфікатори доступу, ми можемо поговорити про фактичні відмінності між класом і структурою в мові C++. Клас за замовчуванням встановлює всім своїм членам специфікатор доступу private. Структура ж за замовчуванням встановлює всім своїм членам специфікатор доступу public.

Є ще одна незначна відмінність: структури успадковують від інших конструкцій мови С++ відкрито, в той час як класи успадковують закрито.

Тест

Завдання №1

a) Що таке відкритий член?

Відповідь №1.а)

Відкритий член — це член класу, доступ до якого мають об’єкти як всередині, так і ззовні класу.

b) Що таке закритий член?

Відповідь №1.b)

Закритий член — це член класу, доступ до якого мають тільки інші члени цього ж класу.

c) Що таке специфікатор доступу?

Відповідь №1.c)

Специфікатор доступу визначає, хто має доступ до членів цього ж специфікатору.

d) Скільки є специфікаторів доступу в мові C++? Назвіть їх.

Відповідь №1.d)

У мові С++ є 3 специфікатори доступу:

   public;

   private;

   protected.

Завдання №2

a) Напишіть простий клас з іменем Numbers. Цей клас повинен мати:

   три закриті змінні-члени типу double: m_a, m_b і m_c;

   відкритий метод з іменем setValues(), який дозволить встановлювати значення для m_a, m_b і m_c;

   відкритий метод з іменем print(), який буде виводити об’єкт класу Numbers в наступному форматі: <m_a, m_b, m_c>.

Наступний код функції main():

Повинен видавати наступний результат:

<3, 4, 5>

Відповідь №2.а)

b) Додайте функцію isEqual() в клас Numbers, щоб наступний код працював коректно:

Відповідь №2.b)

Завдання №3

Тепер спробуємо щось складніше. Напишіть клас, який реалізує функціонал стеку. Клас Stack повинен мати:

   закритий цілочисельний фіксований масив довжиною 10 елементів;

   закрите цілочисельне значення для відслідковування довжини стеку;

   відкритий метод з іменем reset(), який ініціалізуватиме значенням 0 довжину і всі значення елементів;

   відкритий метод з іменем push(), який додаватиме значення в стек. Метод push() повинен повертати значення false, якщо масив вже заповнений, в протилежному випадку — true;

   відкритий метод з іменем pop() для повернення значень зі стеку. Якщо в стеці немає значень, то повинен виводитись стейтмент assert;

   відкритий метод з іменем print(), який буде виводити всі значення стеку.

Наступний код функції main():

Повинен видавати наступний результат:

( )
( 3 7 5 )
( 3 7 )
( )

Відповідь №3

Оцінити статтю:

1 Зірка2 Зірки3 Зірки4 Зірки5 Зірок (2 оцінок, середня: 5,00 з 5)
Loading...

Залишити відповідь

Ваш E-mail не буде опублікований. Обов'язкові поля відмічені *