- •2.1 Елементи концепції ооп .. 20
- •1.1 Коментарі.
- •1.2 Прототипи функцій.
- •1.3 Операція розширення області видимості.
- •1.4 Оголошення в операторах.
- •1.5 Перегрузка функцій.
- •1.6 Значення формальних параметрів по замовчуванню.
- •1.7 Посилання та вказівники.
- •1.8 Специфікатор inline
- •1.9 Операції new та delete .
- •1.10 Вказівник на void.
- •1.11 Зв’язування із збереженням типів
- •1.12 Про структури та об’єднання.
- •2.1 Елементи концепції ооп.
- •2.3 Опис протоколу класу.
- •2.4 Передача повідомлень об’єктам.
- •3 Функції-члени.
- •3.1 Функції-члени в межах та за межами формального опису класу.
- •3.2 Про вказівник this.
- •3.3 Перевантаження функцій-членів. Параметри по замовчуванню.
- •4. Конструктори та деструктори.
- •4.1 Поняття про конструктори.
- •4.2 Деструктори.
- •4.3 Досягнення високої ефективності. Конструктор копіювання.
- •5 Глобальні та локальні об’єкти.
- •6 Статична пам’ять та класи.
- •7. Наслідування
- •7.1 Синтаксична реалізація наслідування
- •7.2 Правила доступу до полів даних
- •7.3 Конструктори та деструктори в похідних класах
- •7.4 Використання заміщуючих функцій-членів.
- •7.5 Похідні класи та вказівники.
- •7.6 Ієрархія типів
- •7.7 Множинне наслідування
- •8 Вiртуальнi функцiї та класи
- •8.1 Віртуальні функції.
- •8.2 Чисті віртуальні функції. Абстрактні класи.
- •8.3 Віртуальні деструктори.
- •8.4 Посилання як засіб для реалізації поліморфізму
- •8.5 Технічна реалізація механізму віртуальних функцій.
- •8.6 Віртуальні базові класи
- •8.6.1 Ієрархії класів та наслідування
- •8.6.2 Віртуальні базові класи
- •8.6.3 Виклик конструкторів та віртуальні базові класи.
- •9 Друзі
- •9.1 Дружні класи.
- •9.2 Дружні функції.
- •10 Перевантаження операторiв.
- •10.1 Перевантаження операторів. Загальний підхід.
- •10.2 Перетворення типів.
- •10.3 Перевантаження деяких операторів.
- •10.3.1 Оператор індексування масиву.
- •10.3.2 Перевантаження оператора виклику функції.
- •10.3.3 Оператор доступу до члена класу.
- •10.3.4 Перевантаження операторів інкремента та декремента.
- •10.3.5 Перевантаження операторів управління пам’яттю (new,delete).
- •10.3.6 Перевантаження оператора присвоювання.
- •11.1 Функціональні шаблони
- •11.1.1 Визначення та використання шаблонів функцiй.
- •11.1.2 Перевантаження шаблонiв функцiї.
- •11.1.3 Cпецiалiзованi функцiї шаблона.
- •11.2 Шаблони класів.
- •11.2.1 Визначення шаблонів класу
- •11.2.2 Константи та типи як параметри шаблону
- •11.2.3 Використання шаблонних класів
- •11.2.4 Спецiалiзацiя шаблонiв класу.
- •11.3 Шаблони та конфiгурацiя компiлятора.
- •11.3.1 Шаблони Smart.
- •11.3.2 Шаблони Global I External.
- •12.2 Переадресація вводу-виводу
- •12.3 Розширення потоків для типів кориcтувача
- •12.4 Операції роботи з потоком як дружні
- •12.5 Форматований ввід-вивід
- •12.5.1 Ширина поля
- •12.5.2 Заповнюючий символ
- •12.5.3 Число цифр дійсних чисел
- •12.5.4 Прапорці форматування
- •12.5.5 Маніпулятори
- •12.6 Стан потоку
- •12.7 Файловий ввід-вивід
- •12.7.1 Конструктори файлових потокiв
- •12.7.2 Вiдкриття файлу
- •12.8 Неформатований ввід-вивід
- •12.9 Деякі функції вводу-виводу
- •12.10 Форматування в пам’яті
- •13 Управління виключеннями
- •13.1 Виключення та стек
- •13.2.1 Синтаксис основних конструкцій
- •13.2.1.1 Використання try та сatch
- •13.2.1.2 Використання throw
- •13.2.2 Тип виключення та конструктор копії
- •13.2.3 Пошук відповідного типу виключення
- •13.2.4 Використання terminate() та некеровані виключення
- •13.2.5 Робота з специфікаціями виключень
- •13.2.6 Робота з непередбаченими виключеннями
- •13.2.7 Робота з конструкторами та виключеннями
- •13.2.8 Динамічні об’єкти
- •13.2.9 Передача значень з конструктора та деструктора
- •13.2.10 Робота з ієрархіями виключень
- •13.2.11 Робота з специфічними класами виключень
- •13.3 Структурне управління виключеннями
- •13.3.1 Використання кадрованого управління виключеннями
- •13.3.1.1 Синтаксис
- •13.3.1.2 Про функцію RaiseException()
- •13.3.1.3 Фільтруючий вираз
- •13.3.1.4 Перехоплення виключення процесора
- •13.3.2 Використання завершуючих обробників виключень
2.3 Опис протоколу класу.
Розглянемо нові типи даних, що задаються за допомогою ключового слова class. Опис класу майже нічим не відрізняється від опису структури. У прикладі з структурою Ttime ми могли б описати аналогічний клас Ttime:
class TTime {
private:
int year;
int month;
int day;
int hour;
int minute;
public:
void Display (void);
};
void TTime::Display (void)
{printf ("year=%d month=%d day=%d hour=%d \
minute=%d \n", p--> year, p--> month, p--> day,\
p--> hour ,p--> minute);}
Схематично опис класу можемо задати наступним чином:
class Ім’я_Класу
{ private:
тип ідентифікатор;
. . . . . . . . . . . . . . . . . . .
тип ідентифікатор;
тип Ім’я_Функції 11(сигнатура);
. . . . . . . . . . . . . . . . . . .
тип Ім’я_Функції 1N1(сигнатура);
protected:
тип ідентифікатор;
. . . . . . . . . . . . . . . . . . .
тип ідентифікатор;
типрезультату Ім’я_Функції21(сигнатура);
. . . . . . . . . . . . . . . . . . .
типрезультату Ім’я_Функції2N2(сигнатура);
public:
тип ідентифікатор;
. . . . . . . . . . . . . . . . . . .
тип ідентифікатор;
типрезультату Ім’я_Функції 31(сигнатура);
. . . . . . . . . . . . . . . . . . .
типрезультату Ім’я_Функції 3N3(сигнатура);
Ім’я_Класу(сигнатура А);
Ім’я_Класу (сигнатура Б)
{ тіло функції }
~ Ім’я_Класу(void);
};
типрезультату Ім’я_Класу:: Ім’я_Функції 11(сигнатура)
{ тіло функції}
типрезультату Ім’я_Класу:: Ім’я_Функції 12(сигнатура)
{тіло функції}
. . . . . . . . . . . . . . . . . . . . . . . . . . .
типрезультату Ім’я_Класу:: Ім’я_Функції 3N3(сигнатура)
{тіло функції}
Ім’я_Класу ::Ім’я_Класу(сигнатура А)
{тіло функції}
Ім’я_Класу (сигнатура Б)
{ тіло функції }
Ім’я_Класу :~ Ім’я_Класу(void)
{ тіло функції }
Всі програмні компоненти, що містяться між відкриваючою та закриваючою фігурними дужками опису класу (“{“ - ”};”) утворюють формальний опис класу. Під протоколом класу будемо розуміти область, що складається з області формального опису класу та тіл функцій-членів, визначених за межами формального опису класу при допомозі операції розширення області видимості.
Бачимо, що формальний опис класу ділиться на три роздiли , що задаються за допомогою ключових слів private, protected та public. Кожен з цих розділів може мiстити поля даних та функцiї-члени. Порядок слідування роздiлiв та їх кiлькiсть можуть бути довiльними. Кількість полів у кожному розділі та порядок їх розміщення також може бути довільним. Якщо ключове слово вiдсутнє , то поля даних i функцiї-члени в цiй частинi опису класу вважаються закритими (для структур -вiдкритими ).
Як бачимо з схеми опису класу, крім “звичайних “ функцій-членів класи можуть мати функції, імена яких співпадають з іменем класу або утворюються по схемі: ~ Ім’я_Класу.Це так звані конструктори та деструктори.
Конструктор - це функцiя-член, iм'я якої спiвпадає з iменем класу. Конструктор може мати порожнiй список параметрiв. Допускаються параметри по замовчуванню, перегрузка. Ціль конструкторів - ініціалізація полів об’єкту (екземпляракласу). Присутність конструктора в протоколі класу не є обов’язковою.
Деструктор - це функція, ім’я якої ~ Ім’я_Класу . Деструктор повинен обов’язково мати порожнiй список параметрiв. В класі може бути не більше одного деструктора. Ціль деструктора - проведення корректних операцій при знищенні екземпляра класу (наприклад, звільнення пам’яті).
Конструктори i деструктори, так само як i iншi функцiї-члени можуть бути визначеними за межами формального опису класу. Якщо визначення функцiї включається в межі формального опису класу, то така функцiя розглядається компілятором як inline -функцiя. Діє правило: будь-яка змінна та функція є доступною в межах протоколу класу. Тобто в межах протоколу класу можна вільно звертатись до будь-якої змінної чи функції, описаної в цьому ж протоколі (так, ніби вони знаходяться в одному складеному операторі). Наприклад, в функції void TTime::Display (void) вільно використовуються поля month, hour та ін. без будь-яких додаткових описів. Що ж стосується доступу до полів ззовні протоколу (випадок коли вже визначений певний об’єкт-екземпляр класу), то прямий доступ можливий лише до полів даних та функцій -членів відкритого розділу (аналогічно, як вже розглядалось стосовно структур). Доступ до полів закритого та захищеного розділів здійснюється лише через функції-члени, що містяться у відкритих розділах.
Як вже відмічалось, обмеженість доступу до полів даних класу має ряд переваг:
а) перший етап вiдладки програми , - локалiзацiя помилки -, виконується ще до запуску програми за рахунок її органiзацiї . Адже помилка, пов’язана з використанням закритих даних, може виникнути лише в функції ( описаній у відкритому розділі), що працює з цими даними.
б) для того, щоб працювати з об’єктами, користувач не обов'язково повинен знати структуру закритих даних. Достатньо лише знати функцiї, якi працюють з цими даними.
в) легко можна змiнювати закриту частину даних без змiни основної програми.
Специфіка захищеного розділу буде розглянута пізніше.
Для ілюстрації пункту б) розглянемо, наприклад , ввід-вивід в С++ (детально він буде розглянутий пізніше). В систему С++ включаються класи ostream та istream. Вивiд iнформацiї здiйснюється шляхом передачi об'єкту cout класу ostream повiдомлення, яке виводиться. Наприклад, якщо хочемо надрукувати рядок " a string", в С++ можемо зробити це так:
cout << " a string\n";
Об'єкту cout можуть передаватись множиннi повiдомлення.
cout <<“ The values i ="<<i<<"\n";
Допускається при цьому форматований вивiд за допомогою функцiї form , параметри якої аналогічні параметрам функції printf:
cout<< form( “ i=%d”,i);
Для вводу потрiбно здiйснити передачу об'єкту cin класу istream повiдомлення iз змiнною, яка приймає данi, що вводяться, в якостi параматра. Аналогічно здійснюється форматований ввiд:
cin>> form( “ i=%d”,&i);
Взагалі, система вводу-виводу С++ є дуже складною. Класи вводу-виводу утворюють складну ієрархію, кожен клас ієрархії має свої функції та поля даних. Проте , користувач може взагалі не знати всієї цієї внутрішньої організації . Достатньо знати лише, яким об’єктам і як передаються відповідні повідомлення. Навіть з кількох наведених вище прикладів та короткої інформації ми формально можемо навчитись вводити та виводити дані в С++ (у найпростіших випадках). При цьому, поки що, для нас залишається незрозумілим, чому саме так і як все відбувається на внутрішньому рівні.