}
};
Отже, клас – це тип, введений програмістом. Кожен тип служить для визначення об’єктів. Для описання об’єкта класу використовується конструкція:
ім’я_класу ім’я об’єкту;
В об’єкти (класу) входять дані (елементи), відповідні компонентам даних класу. Компонентні функції класу дозволяють обробляти дані конкретних об’єктів класу.
Визначення об’єктів класу передбачає виділення ділянки пам’яті та ділення цієї ділянки на фрагменти, відповідні окремим елементам об’єкта, кожен із котрих відображає окремий компонент даних класу.
Як тільки об’єкт є визначеним, з’являється можливість звертатися до його компонент, по-перше, за допомогою «кваліфікованих» імен, кожне з яких має формат:
ім’я_об’єкта.ім’я_класу::ім’я компоненту
Ім’я класу з операцію вказівки області дії «::» звичайно може не використовуватися та дуже часто для доступу к даним конкретного об’єкту заданого класу (як і у випадку структур) використовується уточнене ім’я:
ім’я_об’єкту.ім’я_елементу;
Інший спосіб доступу до елементів об’єкту деякого класу передбачає використання вказівника на об’єкт класу та операції непрямого вибору компонент («–>»):
вказівник_на_об’єкт_класу –> ім’я_елементу;
Вказівник на об’єкт класу дозволяє викликати функції, які належать до класу, для обробки даних того об’єкту, який адресується вказівником.
Для ініціалізації об’єктів класу в його визначення можна явно включати спеціальну компонентну функцію, яка називається конструктор. Формат визначення конструктора в тілі класу може бути таким:
ім’я_класу (список_формальних_параметрів) {оператори_тіла_конструктора};
Приклад конструктора для класу complex:
complex (double re = 0.0, double im = 0.0)
{
real = re;
imag = im;
}
Ім’я цієї компонентної функції за правилами мови С++ повинно збігатися з іменем класу. Така функція автоматично викликається при визначенні або розташуванні в пам’яті за допомогою оператора newкожного об’єкту класу.
Конструктор неможна викликати як звичайну компонентну функцію. Для явного виклику конструктора можна використати дві різні синтаксичні форми:
ім’я_класу ім’я об’єкту (фактичні_параметри_деструктора);
ім’я_класу (фактичні_параметри_деструктора);
Перша форма допускається тільки при непорожньому списку фактичних параметрів. Вона передбачає виклик конструктора при визначенні нового об’єкта даного класу:
complex ss(10.3, 0.22); //ss.real = 10.3;
//ss.imag = 0.22;
complex ee(2.345); //ee.real = 2.345;
//ee.imag = 0.0 (за замовченням)
complexdd();//помилка! Компілятор порахує, що це
//прототип функції без параметрів,
//який повертає значення типа complex
Інша форма явного виклику конструктора приводить до створення об’єкту, який не має імені. Створений таким чином об’єкт без імені можна використовувати у тих виразах, де можна використовувати об’єкт даного класу. Наприклад:
complexzz = complex (4.0, 5.0); //zz.real = 4.0; zz.imag = 5.0;
Динамічне виділення пам’яті для об’єктів якого-небудь класу створює необхідність у звільнені цієї пам’яті при знищенні об’єкту. Таку можливість забезпечую спеціальний компонент класу – деструктор (знищувач об’єктів) класу. Для нього передбачений стандартний формат:
~ім’я_класу () {оператори тіла деструктора};
Назва деструктору в С++ завжди починається з символа тильда «~», за яким без пропусків та інших роздільних знаків поміщується ім’я класу. У деструктора не може бути параметрів (навіть типу void). Деструктор не має повертає мого значення (навіть типу void). Виклик деструктора виконується неявно, автоматично, як тільки об’єкт класу знищується. [3]
1.4. Особливості розробки класів мовою С++
У відповідності до синтаксису мови С++ кожний компонент класу має статус доступу. Таких статуси три: загальнодоступний (public), власний (private) та захищений (protected).За специфікаторами доступу (public, private, protected) йде двокрапка. Дія специфікаторів на компоненти класу починається з моменту написання до нового специфікатора або до кінця описання класу.
Специфікатор доступу privateвикористовується для завдання статусу доступу до елементів даних класу, що дозволяє вирішити проблему захисту даних. Власні дані становляться доступними тільки для методів свого класу. Специфікатор доступу public часто використовується для завдання загальнодоступного доступу методів класу, які організують зв’язок об’єкта даного класу з зовнішнім світом. Статус захищений (protected)використовується в класах при використанні механізму успадкування класів. При відсутності успадкування специфікатор protected еквівалентний специфікатору private.
Усі компоненти класу, введені за допомогою ключових слів struct і union є за замовченням загально ступними, а за допомогою ключового слова class – власними, тобто недоступними для зовнішніх викликів. Для заміни статусу доступу компонентів класу, описаних за допомогою ключових слів classта union, необхідно використовувати специфікатори доступу. Класи, описані за допомогою ключового слова union, не можуть використовуватися як базові класи при успадкуванні. У об’єктів, об’явлених на основі подібного класу, для елементів даних виділяється загальне місце в пам’яті. Статус компонентів у таких класів змінити неможна. [2]
Одним з найважливіших механізмів в С++ є механізм успадкування. Успадкування в будь-якій сучасній мові програмування виконує дві ролі: з одного боку, попереджає дублювання кодів, а з іншого – допомагає розвивати роботу в необхідному направленні. При успадкуванні обов’язково є клас-родитель та клас-нащадок. В С++ клас-родитель прийнято називати базовим, а клас-нащадок – похідним. Відносини між родительським класом та його нащадками називають ієрархією класів.
Простим (або одиночним) називається успадкування, при якому похідний клас має тільки одного родителя. Формально успадкування одного класу от іншого можна завдати наступною конструкцією:
Classім’я_класу-нащадника: [модифікатор_доступу]ім’я_базового_класу
{тіло_класу}
Клас-нащадок успадковує структуру (всі елементи даних) та поведінку (всі функції-методи) базового класу. Модифікатор_доступу визначає доступність елементів базового класу в класі-нащадку. Квадратні дужки говорять о том, що цей модифікатор може бути відсутнім. Цей модифікатор називається модифікатором успадкування.
Існують чотири варіанти успадкування: клас від класу, клас від структури, структура від структури та структура від класу. В залежності від модифікаторів доступу при об’яві базового класу та при успадкуванні, доступність об’єктів базового класу із класів-нащадків змінюється.
В Таблиці 1 приведені усі варіанти доступності елементів базового класу в похідному класі.
Модифікатор в базовому класі | Модифікатор успадкування | Доступ в похідному класі | |
struct | class | ||
public | відсутній | public | private |
protected | відсутній | public | private |
private | відсутній | недоступний | недоступний |
public | public | public | public |
protected | public | protected | protected |
private | public | недоступний | недоступний |
public | protected | protected | protected |
protected | protected | protected | protected |
private | protected | недоступний | недоступний |
public | private | private | private |
protected | private | private | private |
private | private | недоступний | недоступний |
Таблиця 1. Доступ до елементів базового класу в класах-нащадках.
Якщо у якості специфікатора доступу записано слово public, то таке успадкування називається відкритим. Відповідно, при використанні модифікатора protected маємо захищене успадкування, а слово private визначає закрите успадкування.
Також мова С++ підтримує механізм множинного успадкування. Тобто, один клас-нащадок може мати два та більше класів-родителів. Такий клас-нащадок буде успадковувати дані та методи з усіх класів-родителів відповідно до статусу доступу в класів-родителів. Множинне успадкування можна задати такою конструкцією:
Class ім’я_класу-нащадника: [модифікатор_доступу1] ім’я_базового_класу1,
[модифікатор_доступу2]ім’я_базового_класу2,
...
[модифікатор_доступуN]ім’я_базового_класуN
{тіло_класу}
[4]
Мові С++ включає тау властивість, як поліморфізм – можливість для об’єктів різних класів, зв’язаних з допомогою успадкування, реагувати різними способами при виклику однієї функції-елементу. До найважливіших форм поліморфізму можна віднести:
· перевантаження функцій та операцій;
· віртуальні функції;
· узагальнені функції, або шаблони.
Перевантаження функцій та операцій можна визначити як статичний поліморфізм, тому що він підтримується на етапі компіляції. Віртуальні функції відносяться до динамічного поліморфізму, тому що він реалізується при виконанні програм.
В С++ дозволяється наявність декількох однойменних функцій, які виконують аналогічні дії над даними різних типів. Наприклад, в програмі визначені дві функції з прототипами:
intmax(int, int);
floatmax(float, float);
В процесі компіляції програми при виклику функцій max() в залежності від типу та числа аргументів буде здійснюватися завантаження необхідного екземпляра функції. Цей механізм називається перевантаженням функцій.
Одна з найважливіших властивостей поліморфізму – перевизначення стандартних функцій, при якій в залежності від типів даних у виразах викликається необхідний екземпляр операції. Перевизначення може виконуватися для наступних стандартних операцій:
+, –, *, /, =, <, >, +=, –=, *=, /=, <<, >>, <<=, >>=, ==, !=, <=, >=, ++, ––, %, &, ^, !, ~, &=, ^=, |=, |, &&, ||, %=, [], (), new, delete
Не можуть бути перевизначені операції: . , .*, ?:, ::, sizeof.
Перевизначення операції може виконуватися з допомогою визначення операторної функції наступного формату:
тип_результату operatorзнак_операції (список_параметрів)
{оператори_тіла_операторної_функції}