
- •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.1 Елементи концепції ооп.
Об’єктно-орієнтована парадигма пропонує новий підхід до розробки програмного забезпечення. Фундаментальна концепцiя об’єктно-орієнтованої парадигми полягає в передачi повiдомлень об'єктам. Для цього необхiдно, щоб процедури визначались в одному програмному об’єкті разом з даними, якими вони маніпулюють. Відмітимо, що в процедурному програмуванні спочатку визначаються структури даних, якi потiм передаються в процедури як параметри.
Iснує п'ять компонент об’єктно-орієнтованої парадигми (парадигма-концепція):
1 - об'єкт ;
2 - повiдомлення ;
3 - клас ;
4 - наслiдування ;
5 - метод .
Будь-яка об’єктно-орієнтована мова повинна мати властивост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ю об'єкта на повiдомлення. Як правило, метод складається з ряду виразів і може використовувати протокол з іншого класу.
Таким чином, об’єкти належать до окремих класів. Об’єкти обробляють повідомлення у відповідності з методами, заданими в описі класу. Об’єкти мають змінні стану, визначені в описі класу. Змінні стану можуть мати однакові чи різні значення в різних об’єктів (екземплярів класу).
Розглянемо основні поняття об’єктно-орієнтованої парадигми по відно -шенні до С++.
Клас - це новий тип даних , який вводиться за допомогою ключового слова class.
Об’єкт - це змiнна типу ClassName, де ClassName - це ім’я ран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єрархiю класiв . Iснує поняття множинного наслiдування, коли похiдний клас може бути породжений кiлькома базовими.
Потрiбно розрiзняти наслiдування та контейнернi вiдношення. Якщо клас 1 має всi властивостi класу 0, i крiм того , якiсь свої додатковi, то в такому випадку оправдана iєрархiчна структура( наслiдування).
class 1 <- class 0
Про контейнерне вiдношення говорять, якщо об'єкт класу class 0 мiстить об'єкт класу class 1 , тобто одне з полiв класу class0 має тип class 1.
Поліморфізм - цє здатність повiдомлення викликати рiзнi дiї (реакції методів) на етапi виконання програми . Тобто конкретна форма реакції на повiдомлення визначається i зв'язується з об'єктом пiд час виконання програми (пiзнє зв'язування). В С++ поліморфізм проявляється у підтримці наступних механізмів:
1. Перегрузка функцiй (всерединi опису класу можна перегружати функцiї).
2. Перегрузка операцiй.
3. Вiртуальнi функцiї.
2.2 Від структур ANSI С до класів С++.
Синтаксичною основою реалізації концепції об’єктно-орієнтованого програмування стало введення в С++ нових властивостей структур та класів. Розглянемо, як можна прийти до розуміння необхідності цих властивостей, виходячи з точки зору ідеології об’єктно-орієнтованого програмування, поняття об‘єкта. Нехай описана, наприклад, така структура:
struct TTime {
int year;
int month;
int day;
int hour;
int minute; };
TTime v;
Очевидно, що змінна v може використовуватись для збереження інформації про певний час (рік, місяць, день, година, хвилина). Безсумнівно, що нам може бути необхідною функція, яка виводить цю інформацію в певній формі на якийсь стандартний пристрій виводу (монітор, наприклад):
void Display (TTime*p)
{printf ("year=%d month=%d day=%d hour=%d \
minute=%d \n", p-> year, p-> month, p-> day,\
p-> hour ,p-> minute);}
Проте, функція Display семантично дуже пов’язана з структурою Ttime. Це наводить на думку пов’язати функцію з структурою синтаксично. В С++ (на відміну від ANSI C) є така можливість: функцію можна записувати як поле структури. Тоді наш приклад можемо переписати так:
struct TTime {
int year;
int month;
int day;
int hour;
int minute;
void Display (void)
{printf ("year=%d month=%d day=%d hour=%d \
minute=%d \n", p--> year, p--> month, p--> day,\
p--> hour ,p--> minute);}
};
Можна записати функцію-член структури , визначивши її за межами формального опису структури з використанням операції розширення області видимості:
struct TTime {
int year;
int month;
int day;
int hour;
int minute;
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);}
Що ж ми отримали ? Зробивши функцію членом структури , ми не внесли нічого нового з точки зору можливостей . Адже будь-яка зовнішня функція має вільний доступ до полів даних структури (через операцію “.”). Все те, що можна робити з даними за допомогою функції-члена структури можна робити і за допомогою зовнішніх функцій . Проте, в семантичному плані це безсумнівне досягнення. Об’єднання даних та функцій , що працюють з цими даними в одній структурі - це приклад інкапсуляції. Функція-член структури стає ніби властивістю структури. А що ж це за структура, що має якісь властивості? Де її можна використовувати? Очевидно, що такі структури могли б бути корисними для моделювання реальних природних об’єктів. В нашому випадку, наприклад, структура TTime з функцією-членом Display може служити моделлю годинника. Тобто об’єкта, при звертанні до якого ми отримуємо інформацію про час та дату. Але очевидно, що природні об’єкти мають дані, які є скритими від певних зовнішніх об’єктів. Наприклад, спостерігаючи за літаком, можна визначити його швидкість, висоту, тип, але не можна ззовні визначити, скільки у нього залишилося пального та боєприпасів. Тоді приходимо до думки, що деякі поля даних повинні бути закритими. Тобто недопустимим синтаксично повинне бути звертання до цих полів за допомогою, наприклад, операції “ . ”. Так, виходячи з поняття інкапсуляції, приходимо до концепції закритих полів даних. В С++ існують спеціальні службові слова - специфікатори доступу: public, protected та private. Дані, розміщені в розділах protected та private стають доступними лише для функцій-членів і недоступними для зовнішніх функцій. Доступ до них може здійснюватись лише за допомогою функцій, описаних у відкритому розділі.
Оголосимо поля даних в нашому прикладі закритими:
struct TTime {
private:
int year;
int month;
int day;
int hour;
int minute;
public:
void Display (void);
} tt1;
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);}
Тоді при звертанні виду tt1.day компілятор видасть повідомлення про помилку.
Концепція закритих даних є значним кроком вперед з точки зору теорії програмування. Адже в класичному процедурному програмуванні діє правило: дані формують код. Тобто спочатку визначаються структури даних, з якими доводиться працювати, а потім пишуться функції роботи з ними. При такому підході програма стає надзвичайно залежною від структур даних. Припустимо, наприклад, що ми написали величезну кількість функцій, що працюють з полями структури TTime. Але ж дату можна зберігати і в секундах, використовуючи змінну типу long . Уявімо собі, скільки змін потрібно внести в програму, щоб реалізувати цю ідею. Адже потрібно змінювати всі функції типу Display , всі оператори, які звертаються до полів. У випадку ж закритих даних змінити доведеться лише функції-члени структури, які працюють з закритими даними. Все інше може залишитися без змін ! Більше того, можна взагалі писати програму, визначаючи спочатку функціональний інтерфейс і лише на останньому кроці визначати внутрішню структуру закритих даних. Обмеженість впливу даних на код є однією з суттєвих особливостей ООП.
Відмітимо, що структури та класи в С++ мають лише незначні відмінності у властивостях. Іх можна розуміти не лише як типи даних, але і як синтаксично допустимий спосіб утворення типів даних користувача. В С++ ім’я структури чи класу - це тип даних. Якщо, наприклад, в ANSI C хочемо оголосити змінну типу struct TTime, то можемо написати оголошення виду: struct TTime a; Тут обов’язковим є ключове слово struct. В С++ слово struct не обов’язкове. Тобто допускається еквівалентне оголошенння виду: TTime а; Для можливості такого оголошення в ANSI C потрібно використовувати засіб typedef:
typedef struct TTime {
... };
TTime a;