Урок №121. Класи, Об’єкти і Методи

  Юрій  | 

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

 96

Хоча мова C++ надає ряд фундаментальних типів даних (наприклад, char, int, long, float, double і т.д.), яких буває достатньо для вирішення порівняно простих проблем, для вирішення складних проблем функціоналу цих простих типів може не вистачати.

Класи

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

Перерахування та структури — це традиційний (НЕ об’єктно-орієнтований) світ програмування, в якому ми можемо тільки зберігати дані. У C++11 ми можемо створити і ініціалізувати структуру наступним чином:

Для виводу дати на екран (що може знадобитися не раз і не два) хорошою ідеєю буде написати окрему функцію, наприклад:

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

18/11/2018

В об’єктно-орієнтованому програмуванні типи даних можуть містити не тільки дані, але і функції, які будуть працювати з цими даними. Для визначення такого типу даних в мові C++ використовується ключове слово class. Використання ключового слова class визначає новий користувацький тип даних — клас.

У мові C++ класи дуже схожі на структури, за винятком того, що вони забезпечують набагато більшу потужність і гнучкість. Фактично, наступна структура і клас ідентичні за функціоналом:

Єдиною істотною відмінністю тут є public — ключове слово в класі (про нього ми поговоримо детально на відповідному уроці).

Так само, як і оголошення структури, оголошення класу не призводить до виділення будь-якої пам’яті. Для використання класу потрібно оголосити змінну цього типу класу:

У мові C++ змінна класу називається екземпляром (або “об’єктом”) класу. Точно так же, як визначення змінної фундаментального типу даних (наприклад, int x) призводить до виділення пам’яті для цієї змінної, так само і створення об’єкта класу (наприклад, DateClass today) призводить до виділення пам’яті для цього об’єкта.

Методи класів

Крім зберігання даних, класи можуть містити і функції! Функції, визначені всередині класу, називаються методами. Методи можуть бути визначені, як всередині, так і поза класом. Поки що ми будемо визначати їх усередині класу (для простоти), як визначити їх поза класом — розглянемо трохи пізніше.

Клас Date з методом виводу дати:

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

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

18/11/2018

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

Методи класу працюють трохи інакше: всі виклики методів повинні бути пов’язані з об’єктом класу. Коли ми викликаємо today.print(), ми повідомляємо компілятору, щоб він викликав метод print() об’єкта today.

Розглянемо визначення методу print() ще раз:

На що фактично посилаються m_day, m_month і m_year? Вони посилаються на пов’язаний об’єкт today (який визначений caller-ом).

Тому, при виклику today.print(), компілятор інтерпретує:

   m_day, як today.m_day;

   m_month, як today.m_month;

   m_year, як today.m_year.

Якби ми викликали tomorrow.print(), то m_day посилався би на tomorrow.m_day.

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

Детально про те, як передається неявний об’єкт методу, ми поговоримо на відповідному уроці. Ключовим моментом тут є те, що для роботи з функціями, які не є членами класу, нам потрібно передавати дані в цю функцію явно (в якості параметрів). А для роботи з методами у нас завжди є неявний об’єкт класу!

Використання префіксу m_ (англ. m” = “members”) для змінних-членів допомагає розрізняти змінні-члени від параметрів функції або локальних змінних всередині методів класу. Це корисно з кількох причин:

   по-перше, коли ми бачимо змінну з префіксом m_, то ми розуміємо, що працюємо зі змінною-членом класу;

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

Зазвичай програмісти пишуть імена класів з великої літери.

Правило: Пишіть імена класів з великої літери.

Ось ще один приклад програми з використанням класу:

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

Name: John
Id: 5
Wage: $30

Name: Max
Id: 6
Wage: $32.75

На відміну від звичайних функцій, порядок, в якому визначені методи класу, не має значення!

Примітка про структури в C++

В мові програмування Сі структури можуть тільки зберігати дані і не можуть мати пов’язаних методів. Після проектування класів (використовуючи ключове слово class) в мові С++, Б’ярн Страуструп розмірковував про те, чи потрібно, щоб структури (які були успадковані з мови Сі) мали пов’язані методи. Після роздумів він вирішив, що потрібно. Тому у вищенаведених програмах ми також можемо використовувати ключове слово struct, замість class, і все буде працювати!

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

Правило: Використовуйте ключове слово struct для структур, які використовуються тільки для зберігання даних. Використовуйте ключове слово class для об’єктів, які об’єднують як дані, так і функції.

Висновки

Виявляється, Стандартна бібліотека C++ має багато класів, створених для нашої зручності. std::string, std::vector і std::array — це все типи класів! Тому, коли ви створюєте об’єкт будь-якого з цих типів, ви створюєте об’єкт класу. А коли ви викликаєте функцію з використанням цих об’єктів, ви викликаєте метод:

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

Тест

Завдання №1

Створіть клас Numbers, який містить два цілих числа. Цей клас повинен мати дві змінні-члени для зберігання цих двох цілих чисел. Ви також повинні створити два методи:

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

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

Виконання наступної функції main():

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

Numbers(3, 3)
Numbers(4, 4)

Відповідь №1

Завдання №2

Чому для Numbers повинен використовуватися клас, а не структура?

Відповідь №2

Клас Numbers містить як змінні-члени, так і методи, тому ми повинні використовувати клас. Ми не повинні використовувати структури з об’єктами, які мають методи.

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

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

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

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