You are on page 1of 74

МІНІСТЕРСТВО ОСВІТИ І НАУКИ, МОЛОДІ ТА СПОРТУ

УКРАЇНИ
Тернопільський національний технічний університет
імені Івана Пулюя

Кафедра
комп’ютерних наук

МЕТОДИЧНІ ВКАЗІВКИ
до виконання лабораторних робіт
з дисципліни
“Об’єктно-орієнтоване програмування”
I частина
для студентів денної та заочної форм навчання
напряму підготовки
6.050101 – “Комп’ютерні науки”

Тернопіль, 2012
1
МІНІСТЕРСТВО ОСВІТИ І НАУКИ, МОЛОДІ ТА СПОРТУ УКРАЇНИ
Тернопільський національний технічний університет
імені Івана Пулюя

Кафедра
комп’ютерних наук

МЕТОДИЧНІ ВКАЗІВКИ
до виконання лабораторних робіт
з дисципліни
“ Об’єктно-орієнтоване програмування”
I частина
для студентів денної та заочної форм навчання
напряму підготовки
6.050101 – “Комп’ютерні науки”

Тернопіль, 2012

2
Методичні вказівки розроблені у відповідності з навчальним планом
напряму підготовки 6.050101 – “Комп’ютерні науки”

Укладачі: к.т.н., доцент Баран І.О., асистент Бревус В.М.

Рецензент: к.т.н., доцент Касянчук М.М (Тернопільський


національний економічний університет)

Відповідальний за випуск: завідуючий кафедрою КН, д.т.н., професор


Приймак М.В.

Затверджено
на засіданні кафедри комп’ютерних наук
Протокол № 2 від “ 4 ” вересня 2012 р.

Схвалено та рекомендовано до друку методичною комісією


факультету комп’ютерно-інформаційних систем і програмної інженерії
Тернопільського національного технічного університету імені Івана Пулюя.
Протокол № 2 від “ 27 ” вересня 2012 р.

Вказівки складені з урахуванням матеріалів літературних джерел,


названих у списку.

3
ЗМІСТ
ВСТУП ................................................................................................................................................5
ЛАБОРАТОРНА РОБОТА 1.
КОНСТАНТИ, ЗМІННІ, ТИПИ ДАНИХ В С++....................................................................7
ЛАБОРАТОРНА РОБОТА 2.
ПРОЦЕС АНАЛІЗУ ТА ПРОЕКТУВАННЯ ПРОГРАМНИХ СИСТЕМ НА ОСНОВІ
МОВИ UML.................................................................................................................................... 19
ЛАБОРАТОРНА РОБОТА 3.
КЕРУЮЧІ СТРУКТУРИ В С++............................................................................................... 24
ЛАБОРАТОРНА РОБОТА 4.
РОБОТА З ВКАЗІВНИКАМИ. ОПРАЦЮВАННЯ МАСИВІВ ..................................... 29
ЛАБОРАТОРНА РОБОТА 5.
ФУНКЦІЇ. ШАБЛОНИ ФУНКЦІЙ ........................................................................................ 37
ЛАБОРАТОРНА РОБОТА 7.
РОБОТА З КЛАСАМИ. РЕАЛІЗАЦІЯ ПРИНЦИПУ НАСЛІДУВАННЯ. ................. 57
ЛАБОРАТОРНА РОБОТА 8.
РЕАЛІЗАЦІЯ ПРИНЦИПУ ПОЛІМОРФІЗМУ В ООП. ПЕРЕВАНТАЖЕННЯ
ОПЕРАЦІЙ..................................................................................................................................... 64
ЛАБОРАТОРНА РОБОТА 9.
ВІРТУАЛЬНІ ФУНКЦІЇ . ШАБЛОНИ КЛАСІВ ............................................................... 68
ВИКОРИСТАНА ЛІТЕРАТУРА ............................................................................................. 73
ДОДАТКОВА ЛІТЕРАТУРА ................................................................................................... 74

4
Вступ

Протягом останніх декількох десятиліть комп'ютерні технології


розвивались вражаючими темпами. Мови програмування також зазнали
значних змін. Поява більш потужних комп'ютерів дала життя більш об'ємним і
складним програмам, які, водночас, висвітлювали нові проблеми в області
керування програмами, а також їх подальшому супроводу. Ще у 70-ті роки 20
ст. такі мови програмування, як С та Pascal, допомогли людству увійти в епоху
структурного програмування, яке на той час відчайдушно потребувало
наведення у цій області деякого порядку. Мова програмування С надала в
розпорядження програмістів інструменти, необхідні для реалізації структурного
програмування, а також забезпечила створення компактних, швидко
працюючих програм і можливість адресації апаратних ресурсів (наприклад,
можливість керування портами зв'язку і накопичувачами на магнітних носіях).
Ці властивості допомогли мові С у 80-ті роки 20 ст. дещо домінувати над
іншими мовами програмування. В той же час з'явилася і нова технологія
створення та удосконалення програм – об’єктно-орієнтоване програмування
(ООП), втіленням якого стала спочатку мова С++.
ООП – одна з парадигм програмування1, яка розглядає програму як
множину "об'єктів", що взаємодіють між собою. В ній використано декілька
технологій від попередніх парадигм, зокрема успадкування, модульність,
поліморфізм та інкапсуляцію. Незважаючи на те, що ця парадигма з'явилась ще
в 1960-тих роках, вона не мала широкого застосування до 1990-тих. Сьогодні
багато мов програмування (зокрема, Java, C#, C++, Python, PHP, Ruby,
Objective-C, ActionScript 3) підтримують ООП.
Базовою мовою ООП для данного курсу є мова C++. Тим не менш,
основний акцент робиться на концепції і принципах ООП, а не відомостях про
мову C++. Принципи, які ви дізнаєтеся в цьому курсі, однаково можуть бути

1
Парадигма програмування – основні принципи програмування (не плутати з розробленням програм),
або, парадигмне програмування. Парадигма програмування надає (та визначає) те, як програміст розглядає
роботу програми. Наприклад, в об'єктно-орієнтованому програмуванні, програміст розглядає програму як
множину взаємодіючих між собою об'єктів, водночас як у функційному програмуванні програму можна
представити як обчислення послідовності функцій без станів.
1
Основні парадигми програмування: процедурне програмування (англ. Procedural programming);
модульне програмування (англ. Modular programming); об'єктно-орієнтоване програмування (англ. Object-
oriented programming); функційне програмування (англ. Functional programming); імперативне програмування
(англ. Imperative programming); декларативне програмування (англ. Declarative programming); прототипне
програму-вання (англ. Prototype-based programming); аспектно-орієнтоване програмування (англ. Aspect-oriented
prog-ramming); предметно-орієнтоване програмування (англ. Subject-oriented programming); функціонально-
орієнтоване програмування (англ. Feature-oriented programming).
5
застосовані і до інших об’єктно орієнтованих (OO) мов програмування,
наприклад, Java, Eiffel.
Ви не отримаєте хорошої оцінки в цьому курсі просто за написання
програм. Основні бали будуть нараховуватись за хороший OO дизайн та
відповідну реалізацію цього в коді C++. Легко писати програми C++, які не
відповідають OO принципам, але такі програми не будуть отримувати
необхідний прохідний бал.
Дані методичні вказівки призначені для виконання лабораторних робіт у
першому семестрі вивчення дисципліни “Об’єктно-орієнтоване програмування”
для студентів спеціальності 6.050101 “Комп’ютерні науки” денної та заочної
форм навчання.
Виконання лабораторних робіт повинно забезпечити закріплення
теоретичних знань, отриманих при вивченні лекційного матеріалу, та
практичної частини дисципліни.
В методичних вказівках розглянуті основні теоретичні питання, пов’язані
з виконанням лабораторних робіт.

Додаткові ресурси
Програмне забезпечення
Під час роботи з курсом ви будете розробляти, компілювати та тестувати
програми. Ось чому вам буде потрібно організувати C++ робоче середовище:
текстовий редактор, компілятор та стандартні бібліотеки.
Хоча маємо велику кількість С++ середовищ, проте для роботи з цим
курсом слід використовувати GNU g++ компілятор (ISO/IEC стандарт C++,
native C++) і пов'язані з ними бібліотеки. Це середовище ви зможете отримати
як в Linux операційній системі так і у Windows – Cygwin (реалізація Unix
середовища під Windows) та MinGW. З MinGW можна ознайомитися на
http://www.mingw.org. Додаткові відомості про використання MinGW наведені
у лабораторній роботі 1. Рекомендований текстовий редактор для Windows –
Notepad++ (http://notepad-plus-plus.org/), для Linux – Vim чи будь-який з
підсвіткою коду.

6
Лабораторна робота 1. Константи, змінні, типи даних в С++.

Мета роботи: систематизувати вміння та навички програмування,


отримати навички роботи з типами даних та виразами, а також із
середовищем розробки програм.

1.1 Ви навчитесь:
По завершенні цього розділу ви будете вміти:
 використовувати термінологію мови програмування C++
 описати структуру програми
 порівняти мову C та С++, ознайомитесь з особливостями останньої
 створювати, редагувати, компілювати та виконувати прості
програми, написані на мові C++

1.2 Теоретичні відомості


Алфавіт мови (його символи) це основні неподільні знаки, за допомогою
яких пишуться всі тексти мовою.
Ідентифікатор — це послідовність букв, цифр і символів підкреслення.
 букви верхнього та нижнього регістрів є різними
 ідентифікатор не може починатися з цифри
 довжина може бути будь-якою, але багато систем розпізнають
тільки 31 символ (у мові С -8 символів)
Приклади
 n // чисельна змінна
 number // осмислене ім'я
 buffSize // стиль об’єктно-орієнтованого програмування
 q243 // складно для розуміння
 cout // використовується в iostream.h,
 _my // обережно, з підкреслення часто починаються системні
ідентифікатори
 for, 3q, сount // невірно
Ідентифікатори з подвійним символом підкреслення зарезервовані для
системних цілей: __sys ident, sys__ident
Ключові слова — зарезервовані ідентифікатори, що мають у С++
фіксований зміст,мають спеціальне значення для компілятора.
Лексема — мінімальна одиниця мови, що має самостійний зміст,
складається із символів алфавіту, що розпізнається компілятором.

7
Наприклад, оператор do — це лексема Зустрічаючи цю лексему,
компілятор знає, який машинний код потрібно підставляти замість неї.
Лексеми утворяться із символів, вирази — з лексем і символів,
оператори — із символів, виразів і лексем
Вираз — це послідовність знаків операцій, операндів і круглих дужок, що
задає обчислювальний процес знаходження результату певного типу.
Найпростішим виразом є константа, змінна або виклик функції. Можна
вважати, що при виконанні програми результат виразу замінює сам вираз.
Прості вирази містять символ операції та операнди. Прикладом простого
виразу з бінарною операцією є віднімання: 3.4 – x.
Операнд є елементом-учасником операції. Операндами можуть бути
константи, змінні, виклики функцій і вирази.
Операції і вирази мови С++ дозволяють задати певну послідовність дій.
Блоки і складові оператори
Будь-яка послідовність операторів, що взяті в фігурні дужки, є складовим
оператором (блоком). Складовий оператор не повинен закінчуватися (;),
оскільки обмежувачем блоку служить сама дужка, яка закривається. Всередині
блока кожний оператор повинен обмежуватися (;). Складовий оператор може
використовуватися скрізь, де допускається застосування звичайного оператора.
1.2.1 Константи
Константи – це вирази із фіксованим значенням. Типи констант:
 літерали: використовуються для того щоб представити певне
значення в коді; можуть бути цілими числами (1, 0, -17), дійсними
(3.1415926535897, 1., 6.096, -3.), символами (‘a’, ‘ ’, ‘\n’), рядком
символів (“6.096”, “a”), мати логічне значення (true, false).
 символьні константи, визначені за допомогою директиви #define
1 # include < iostream >
2
3 using namespace std ;
4
5 # define PI 3.14159
6 # define NEWLINE ’\n ’
7
8 int main ()
9 {
10 double r = 5.0;
11 double circle ;
12
13 circle = 2 * PI * r; // circle = 2 * 3.14159 * r;
14 cout << circle << NEWLINE ; // cout << circle << ’\n ’;
15
16 return 0;
17 }

8
 Оголошені константи (const), користувацькі константи з префіксом
(const)
1 const int pathwidth = 100;
2 // pathwidth = 2; this will cause a compiler error!
3 const char tabulator = ’\t ’;
4 cout << "tabulator =" << tabulator << ’\n ’;

1.2.2 Оператор присвоювання «=» (L-values, R-values)


Символ «=» означає бінарну операцію простого присвоювання, у
результаті виконання якої значення правого операнду рівне значенню лівого.
Порядок обчислення виразу визначається розташуванням знаків операцій,
круглих дужок і пріоритетами виконання операцій. Вираз із найвищим
пріоритетом обчислюються першими. Пріоритети операцій подані в табл.1.
Операції на початку таблиці мають більш високий пріоритет.
Якщо у виразі міститься декілька операцій одного пріоритету на тому
самому рівні, то їх обробка виконується відповідно до порядку виконання: зліва
направо чи справа наліво.

Таблиця 1.1 Пріоритети та порядок виконання операцій


Пріо- Знаки операцій Назви операцій Порядок
ритет виконання
1. . вибір елемента за іменем зліва-направо
-> вибір елемента за вказівником
[] вибір елемента за індексом
() виклик функції або конструювання значення
++ постфіксний інкремент
-- постфіксний декремент
2. sizeof розмір операнда в байтах справа-наліво
++ префіксний інкремент
-- префіксний декремент
~ інверсія (порозрядне заперечення)
! логічне заперечення
+ унарний плюс
- унарний мінус
& адреса
new виділення пам'яті або створення
delete звільнення пам'яті або знищення
(ім'я_типу) перетворення типу
3. .* вибір елемента по імені через вказівник зліва-направо
->* вибір елемента по вказівнику через вказівник
4. * множення зліва-направо
/ ділення
% остача від ділення цілих (ділення по модулю)
5. + додавання зліва-направо
- віднімання
6. << зсув вліво зліва-направо
>> зсув вправо

9
7. < менше зліва-направо
> більше
<= менше або дорівнює
>= більше або дорівнює
8. == дорівнює зліва-направо
!== не рівне
9. & порозрядне І зліва-направо
10. ^ порозрядне виключаюче АБО зліва-направо
11. | порозрядне АБО зліва-направо
12. && логічне І зліва-направо
13. || логічне АБО зліва-направо
14. ?: умовна операція справа-наліво
15. = присвоювання (просте і складене) справа-наліво
*=, /=, %=,
+=, -=,
&=, ^=, |=
16. throw генерація виключення справа-наліво
17. , послідовність виразів зліва-направо

Приклади:
1 int var; // var - це L-value,
2 //тому що можна його поставити зліва від знаку =, наприклад
3 //var = 3;

1 y = (x=5);// (x=5) може бути розміщено справа від знаку, тобто


2 // є R-value x=5) повертає значення 5

До операцій присвоювання відносять = , += , -= , *= , /= , %= , <<= , >>= ,


&= , ^= , |= , а також префіксні і постфіксні операції ++ та --. Всі операції
присвоювання присвоюють змінній результат обчислення виразу. Якщо тип
лівої частини присвоювання відрізняється від типу правої частини, то тип
правої частини приводиться до типу лівої.
У одному операторі операція присвоювання може зустрічатися декілька
разів. Обчислення відбуваються справа наліво.
Наприклад: a = ( b = c ) * d;
Спочатку змінний b присвоюється значення с, потім виконується
операція множення на d, і результат присвоюється змінний а.
Операції +=, -=, *= і /= є скороченою формою запису операції
присвоювання. Їхнє застосування проілюструємо за допомогою такого опису:
a += b означає a = a + b
a -= b означає a = a-b.
a *= b означає a = a*b.
a /= b означає a = a/b.

10
Префіксні і постфіксні операції ++ та -- використовують для збільшення
(інкремент) і зменшення (декремент) на одиницю значення змінної.
Семантика зазначених операцій така:
++a (--a) збільшує (зменшує) значення змінної а на одиницю до
використання цієї змінної у виразі.
а++ (a--) збільшує (зменшує) значення змінної а на одиницю після
використання цієї змінної у виразі.

1.2.3 Оголошення змінних


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

[<специфікатор класу пам'яті>] [const] <специфікатор типу> <ідентифікатор> [=


<початкове значення>] , [<ідентифікатор> [= <початкове значення>]] ;
int a=5, у;

Кожна змінна, оголошена в програмі, має дві найважливіші


характеристики:
 час існування;
 область видимості.
Ці характеристики взаємозалежні та істотно впливають на можливості
використання змінної у програмі. Взаємозв'язок характеристик визначається
способом виділення пам'яті для змінної.
Час існування, або час життя змінної, вимірюється у наступних двох
відносних одиницях.
Локальний час життя — це час існування змінної при виконанні блоку, у
якому вона оголошена.
Глобальний час життя — це час існування змінної при виконанні всієї
програми.
Область видимості, або область дії змінної, також вимірюється в двох
відносних одиницях.
1. До кінця блоку, у якому оголошена змінна.
2. До кінця файлу, у якому оголошена змінна.

11
Керувати цими характеристиками змінних програміст може двома
шляхами:
1. зміною місця оголошення змінної у програмі;
2. використанням модифікаторів auto, register, static, extern.

1.2.4 Класифікація типів даних


Під типом даних розуміють множину допустимих значень цих даних і
множину дозволених операцій над ними. Водночас тип даних визначає і розмір
пам'яті, що займають змінні і константи даного типу. Кожен тип даних має ім'я
(ідентифікатор). Пам'ять не виділяється для типу даних, а виділяється для
розміщення змінної або константи.
У мові С++ виділяють наступні категорії типів:
 базові типи даних;
 похідні типи.
Базові типи мають імена, які є ключовими словами мови.
До базових типів належать: скалярні типи і порожній тип — void.
Тип void не має значення і введений, в основному, для опису функцій, які
не повертають значень.
Скалярні типи поділяються на цілочисельні та дійсні типи.

Таблиця 1.2.Характеристики основних типів даних мови С++


Ім'я типу Розмір пам'яті, байтів Діапазон значень для 16-розрядної
( 16/32-розрядна) архітектури
[signed] char 1 -128 127
unsigned char 1 0 255
[signed] short [int] 2 -32768 32767
unsigned short [int] 2 0 65535
Ім'я типу Розмір пам'яті, байтів Діапазон значень для 16-розрядної
( 16/32-розрядна) архітектури
[signed] int машинне слово -32768 32767
unsigned int машинне слово 0 65535
[signed] long [int] 4 -2147483648 2147483647
[unsigned] long [int] 4 0 4294967295
float 4 3.4e-38 3.4e38
double 8 1.7e-308 1.7e308
long double 10 3.4e-4932 3.4e4932

Логічний тип, символьні і цілі типи даних є цілочисельним типом, для


якого визначені всі операції з цілими числами.
12
Похідні типи визначаються на основі базових типів. Похідні типи
поділяються на скалярні і структурні (агрегатні).
До скалярних похідних типів належать:
 перерахування (enum — enumeration) — множина поіменованих
цілих значень;
 вказівники (ім'я_типу*);
 посилання (ім'я_типу&).
Структурні типи:
 масиви (тип_елементу ім'я_масиву[число_елементів]);
 структури (struct);
 об'єднання (union),
 класи (class).

1.2.5 Структура програми


Програма на мові C++ є блочно-структурованою та, як правило, містить
деякий набір функцій. Функція — це іменована частина програми, до якої
можна звертатися з її інших частин, вказуючи її ім’я, наприклад,
SimpleFunc(5,1.9). У даному випадку функції з іменем SimpleFunc передається
два числових параметра. Питання створення та використання функцій більш
докладно розглядаються у наступних лабораторних .
До складу кожної програми на мові С++ повинна входити головна
функція main(). Саме ця функція є початковою точкою входу в програму.
Крім функції main() до програми може входити будь-яка кількість
функцій. Кожна функція по відношенню до іншої є зовнішньою, тобто жодна з
функцій не може міститися всередині іншої. Для того, щоб функція була
доступна, необхідно, щоб до її виклику про неї було відомо компілятору.
Основну структуру програми на мові С++ наведено на рис. 1.1.
Директиви
Програма препроцесор
на С++ а
#Заголовок Функції
складаютьс
я з
main( ) операторів
Оператори

Функція a( )
Оператори

Функція b( )

Оператори

Рис.1.1 Структура програми на С++

13
Нижче наведено приклади двох простих програм на мові С++
Приклад 1.1 Програма виводу на екран привітання “Hello, world!”
1 #include <iostream>
2 // директива препроцесора
3 using namespace std;
4 // включає в програму визначення
5 // стандартного простору імен
6 int main()
7 // заголовок функції main()
8 {
9 // початок тіла функції main()
10 cout<<"Hello, world! \n”;
11 // \n - символ нового рядка
12 cin.get();
13 //очікується натискання будь-якої клавіші
14 return 0;
15 //оператор повернення завершує функцію main()
16 }//кінець тіла функції main()

Приклад1.2. Програма вводу з клавіатури та виводу на екран цілого числа


1 #include <iostream>
2 // директива препроцесора
3 using namespace std;
4 // включає в програму визначення стандартного простору імен
5 int main()
6 {
7 int a;
8 // оголошення змінноїa цілого типу
9 cin>>a;
10 //зчитування змінної а з стандартного потоку введення
11 cout<<“Ви ввели число”<<a<<endl;
12 //запис тексту та змінної а в стандартний потік виведення
13 return 0;
14 //оператор повернення завершує функцію main()
15 }

У наведеному прикладі endl — це маніпулятор виведення, що вставляє у


вихідний потік символ переходу на новий рядок (аналогічно \n).
В C++ консольні оператори введення і виведення (стандартний
консольний пристрій введення – клавіатура, а виведення – екран монітора) не
розглядаються як частина мови. Мова має бібліотеки, які реалізують консольне
введення і виведення. C++ використовує різноманітні бібліотеки введення-
виведення. Файл-заголовок <iostream> дозволяє програмам на C++ виконувати
консольні операції введення-виведення, тобто введення даних з клавіатури і
виведення на екран.

14
1.2.6 Засоби введення/виведення
При запуску програми на мові С++ автоматично створюється декілька
стандартних потоків, зокрема: cin (стандартний потік вводу з клавіатури) та
cout (стандартний потік виводу на екран).
Існує ще 2 стандартних потоки cerr та clog, що призначені для виводу
помилок. Для того щоб використовувати ці потоки, достатньо під’єднати
заголовний файл <iostream> та вказати стандартний простір імен, як це
показано у прикладі 1.2.
Потоки є засобом вводу/виводу мови програмування С++. Крім потоків
для вводу/виводу інформації можна використовувати також функції мови С,
зокрема функцію printf() та scanf(), проте стандарт цього не рекомендує.

1.3 Порядок виконання


1.3.1 Налаштування робочого середовища C++ для ОС Windows:
 завантажимио з сайту http://www.mingw.org/ інсталяційний файл.
 виконаємо даний файл, під час інсталяції слід вибрати будь-який
іншй диск окрім системного (в шляху не має бути пробілів та
кириличних символів)
Для перевірки інсталяції компілятора створимо та виконаємо тестову
програму:
 створимо текстовий файл hello.cpp в робочій папці
 відредагуємо його наступним чином та збережемо зміни
1 // A Hello World program
2 # include <iostream>
3
4 int main () {
5 std::cout << "Hello , world!\n";
6
7 return 0;
8 }

 у консолі перейдемо у каталог, де розміщується цей файл та


виконаємо комнаду g++ hello.cpp -o hello.exe
 виконаємо програму, потрібно у консолі вказати ім’я бінарного
файлу, що був створений внаслідок компіляції hello.exe
Повинні отримати наступний результат: Hello , world!

1.3.2 Пояснення коду програми


1. // вказує на те що все що справа аж до кінця рядка є коментарем та
ігнорується компілятором. Інший варіант коментаря /* ... */ (x = 1 + /*sneaky

15
comment here*/). Такий коментар може займати декілька рядків. Коментарі
існують, для пояснення неочевидних речей в коді. Використовуйте коментарі –
добре документуйте код!
2. Рядок, що починається з # - це команда для препроцесора, що вказує який ще
код має бути скомпільований. #include вказує препроцесору залучити вміст
іншого файлу, в нашому випадку iostream файл, що визначає процедуру
вводу/виводу даних.
4. int main() {...} визначає код, що буде виконаний при запуску програми.
Фігурні дужки дозволяють згрупувати декілька команд в один блок, більше про
це в подальшому матеріалі.
5.
● cout << : дозволяє реалізувати вивід текстової інформації на екран.
Детальніше буде розглянуто пізніше.
● Namespaces: У С++ ідентифікатори можуть бути визначені з контексту
програми, завдяки використанню простору імен (каталогів імен). Коли
хочемо отримати доступ до ідентифікатора в певному просторі імен, то
використовуєм оператор :: (scope resolution operator ), щоб дати
відповідну інструкцію компілятору. В даній програмі вказуєм
компілятору шукати ідентифікатор cout в просторі імен std, в якому
оголошено багато стандартних ідентифікаторів С++.
Кращою альтернативою є додати наступну стрічку коду перед рядком 2.
using namespace std; це вкаже компілятору шукати в просторі імен std всі
неоголошені ідентифікатори. Якщо зробити це, то можна опустити префікс std::
при звертанні до cout. Це є рекомендованою реалізацією.
● Strings: Послідовність символів Hello, world називають стрічкою.
Стрічка, що явно ініцалізується в коді називається стрічковим літералом.
● Escape sequences: \n вказує на створення нового рядка. Це приклад
екранованої послідовності.
7. return 0 Вказує на те що програма після успішного виконання повинна
повернути ОС. Детальніше буде розглянуто в наступних роботах.
Зауважте, що кожен вираз закінчується ; (окрім директив препроцесора та
блоків {...}). Недотримання цього правила є досить поширеною помилкою.

1.3.3 Індивідуальні завдання


1.3.3.1 Вивчити базову структуру програми на С++
Cкласти програму, яка містить мінімально необхідну кількість
програмного тексту і скомпілювати її. Додати необхідні оператори, щоб
організувати виведення короткого повідомлення на екран. Вивчити синтаксис
та можливості основних операторів введення-виведення, в коментарях
задокументувати програму.
Скласти і роздрукувати програму, що вводить необхідні анкетні дані про
студента і виводить їх у відформатованому вигляді. При цьому слід
використовувати засоби введення–виведення зі стандартних бібліотек.
16
Передбачити можливість введення даних всіма способами:
– за допомогою стандартного потоку,
– за допомогою макросів,
– за допомогою змінних, ініціалізованих при описі.
Виведення даних здійснювати за допомогою стандартного потоку.
Типи для представлення змінних вибирати, виходячи із структури даних,
яку необхідно відобразити (наприклад, для відображення року змінна може
бути типу int, а для представлення росту у метрах потрібно змінну типу float).

1.3.3.2 Що буде результатом виконання наступних програм, детальна


відповідь

А) Б) В)
1 #include <iostream> 1 #include <iostream>
2 using namespace std; 2 using namespace std; 1 #include <iostream>
3 int main() 3 int main() 2 using namespace std;
4 { 4{ 3
5 int arg1; 5 int arg1; 4 int main()
6 arg1=-1; 6 arg1=-1; 5 {
7 int x,y,z; 7{ 6 cout<<"Hello
8 char MyDouble='5'; 8 char arg1='A'; 7 World!\n";
9 char arg1='A'; 9} 8 return 0;
10 cout<<arg1<<"\n"; 10 cout<<arg1<<"\n"; 9 }
11 return 0; 11 return 0; 10
12 } 12 }

1.4 Порядок захисту


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

1.5 Контрольні запитання


1. Що таке парадигма програмування?
2. Які парадигми програмування можуть бути реалізовані в С++?
3. Як відбувається процес компілювання програми в C++?
4. Пояснити зміст поняття оператор.
5. Що розуміється під типом даних? Які типи даних ви знаєте?
6. Яка інформація повідомляється компілятору при оголошенні
констант?
17
7. Яким чином розрізняються змінні за часом життя?
8. Дати означення виразу.
9. Привести приклади операцій з однаковим пріоритетом.
10.Вказати операції з найвищим та найнижчим пріоритетом.
11.Назвати тип даних, який забезпечує найбільший діапазон
представлення чисел.
12.Вказати, як впливає тип операндів арифметичної операції на тип
результату цієї операції.

18
Лабораторна робота 2. Процес аналізу та проектування програмних
систем на основі мови UML

Мета роботи: отримати навички аналізу та проектування


програмних систем на основі мови UML.

2.1 Ви навчитесь:
По завершенні цього розділу Ви будете вміти:
 користуватись термінологією UML
 будувати найпростіші діаграми класів

2.2 Теоретичні відомості


Безперечно, розробка сучасних програмних продуктів неможлива без
попереднього моделювання. Накопичений досвід засвідчує: чим більшим і
складнішим є проект, тим важливішим стає моделювання майбутньої системи.
Не варто сподіватися на успішність проекту, якщо не приділено достатньої
уваги попередньому моделюванню системи.
Моделі наочно демонструють бажану структуру та поведінку системи,
відображають її архітектуру та допомагають уточнити деталі проекту з
замовником для мінімізації майбутніх ризиків.
Модель – це спрощене представлення реальності, своєрідне “креслення”
системи. Кожну систему можна описати по-різному, використовуючи різні
моделі, кожна з яких є семантично замкнутою абстракцією системи.
Моделювання дає змогу розв’язати такі задачі:
 візуалізація системи – візуальне відображення програмної
системи у її поточному чи бажаному стані;
 специфікація системи – визначення структури і/або поведінки
системи;
 конструювання системи – отримання шаблону, який допоможе
сконструювати систему;
 документування системи – фіксація прийнятих рішень на основі
отриманих моделей.

Уніфікована мова моделювання (Unified Modeling Language,UML) – це


графічна мова для специфікації, візуалізації, конструювання і документування
програмних систем. За допомогою UML можна розробити детальний план такої
19
системи, який відображатиме і концептуальні елементи системи (системні
функції та бізнес-процеси), і особливості її реалізації (класи, схеми баз даних,
програмні компоненти багаторазового використання тощо).
Авторами мови є Грейді Буч (Grady Booch), Джеймс Рамбо (James
Rumbaugh) і Айвар Якобсон (Ivar Jacobson).
Сьогодні UML є загальновизнаним стандартом, який використовує
більшість розробників системного та прикладного програмного забезпечення.
Знань UML вимагають не лише від системних аналітиків та проектувальників,
але й від звичайних програмістів і тестувальників програмного забезпечення.
Постійно збільшується ринок UML-орієнтованих інструментальних засобів,
призначених для автоматизації процесу розробки програм.
UML призначено для моделювання програмних систем. Самі автори UML
визначають її як графічну мову моделювання загального призначення, яку
використовують для специфікації, візуаліації, конструювання і документування
усіх артефактів2, які створюються під час розробки програмних систем.
Найбільш важливим засобом UML є набір різних видів діаграм. Діаграми
класів ілюструють відносини між різними класами, діаграми об'єктів – між
окремими об'єктами, діаграми зв'язків відображають зв'язки між об'єктами у
часі і т.д. Усі ці діаграми, по суті, відображають погляди на структуру програми
і її функціонування з різних точок зору.
Окрім ілюстрації структури коду програми, UML має немало інших
корисних можливостей. Фактично UML можна використовувати на всіх етапах
реалізації проекту – від усвідомлення та аналізу завдання, розроблення та
відлагодження програми до документування, тестування і підтримки.
Проте не варто розглядати мову UML як засіб розроблення програмного
продукту. Середовище UML є тільки засобом для ілюстрації структури проекту,
який розробляється. Незважаючи на можливість застосування середовища UML
до будь-якої мови програмування, однак вона є найбільш корисною під час
застосування об'єктно-орієнтованого програмування мовою С++.
ООП є способом організації коду програми. Основну увагу під час його
вивчення приділено організації програми, а не питанням написання коду
програми. Головним компонентом об'єктно-орієнтованого коду програми є
об'єкт, який містить глобальні дані та функції для роботи з ними. Клас є
формою або зразком для визначення множини схожих між собою об'єктів.
Універсальна мова моделювання UML є стандартизованим засобом
візуалізації структури і функціонування коду програми за допомогою діаграм.
Архітектурний базис UML визначає базові поняття, якими оперує мова:
сутності, відношення та діаграми.

2
Будь-який створений і відчужений матеріал проекту (модель, програм-ний код, документація тощо).
20
Сутності – це певні абстракції, які є базовими елементами моделей. В
UML є чотири типи сутностей: структурні (актори, класи, інтерфейси,
компоненти, вузли), поведінки (преценденти, діяльності, стани і
повідомлення), групування та анотаційні.
Структурні сутності – це статичні поняття, які відповідають
концептуальним, логічним чи фізичним елементам системи. Структурні
сутності, зазвичай, позначають іменниками. Розрізняють п’ять головних
структурних сутностей: актори, класи, інтерфейси, компоненти, вузли. Кожна з
сутностей може мати свої підвиди3.
Актор (Actor) – це суб’єкт, який перебуває поза системою, що
моделюється, і безпосередньо з нею взаємодіє. Графічно акторів зображають
значком “худа людина”, під яким вказують ім’я актора (рис. 2.1).

Рис. 2.1 Зображення актора

Клас (Class) – це сукупність однотипних сутностей предметної області


(об’єктів) зі спільними атрибутами, операціями, відношеннями та семантикою.
В UML класи зображають прямокутником, розділеним на три секції, в
яких записують назву класу, атрибути та операції, відповідно (рис. 2.2). Назву
абстрактного класу позначають курсивом. Атрибути та операції мають чітко
визначені формати запису, які відображають їхні найважливіші характеристики
(назви, типи тощо). За необхідності секції атрибутів і/або операцій опускають.
Об’єкти (Objects) – це екземпляри класів з конкретними значеннями
атрибутів. Об’єкт має зображення, подібне до зображення класу, проте назву
об’єкта підкреслюють і записують у вигляді:<назва об’єкта>:<назва класу>.
Якщо ідентифікація об’єкта неважлива, то вказують лише назву класу, до якого
належить об’єкт::<назва класу>. При зображенні об’єктів секції атрибутів та
операцій, здебільшого, опускають.

Рис. 2.2. Зображення класу

3
Поділ на головні сутності та їхні підвиди строго не фіксується, отож у літературі трапляється й дещо
інша класифікація сутностей.

21
Анотаційна сутність – це коментар для пояснення чи зауваження до будь-
якого елемента моделі. Є тільки один тип анотаційної сутності– примітка (note).
Графічно примітку зображають прямокутником із загнутим правим верхнім
кутом [2].
Діаграма UML – це графічне зображення елементів cистеми у формі
зв’язаного графа з вершинами (сутностями) і ребрами (відношеннями).
Детальніше можна ознайомитись в матеріалах лекцій та додатковій літературі

2.3 Порядок виконання


1 Ознайомитись із типами діаграм в UML [2].
2 Побудувати діаграму класів (у відповідності до варіанту), використавши
спеціалізований редактор, з врахуванням необхідності приховання даних,
передбачити методи класу:
Варіант1: Клас “учасник”: прізвище, телефон, адреса.
Варіант 2: Клас “фігура”: координати на шахівниці, колір. Метод – “хід”
на одну позицію в одному з чотирьох напрямків.
Варіант 3: Клас “фігура”: координати на шахівниці, колір. Метод – “хід”
в одному з двох напрямків.
Варіант 4: Клас “прямокутник”: координати верхнього лівого і нижнього
правого кутів, порядковий номер.
Варіант 5: Клас “нота”: назва, октава, тривалість звучання.
Варіант 6: Клас “іграшка”: ціна, назва, кількість на складі.
Варіант 7: Клас “годинник”: стиль відображення (військовий формат – 24
години чи стандартний – 12), години, хвилини, секунди. Метод “плюс секунда”
– збільшити поточне значення часу на 1 с.
Варіант 8: Клас “Товар”: назва, порядковий номер, постачальник, ціна,
кількість одиниць.
Варіант 9: Клас “Точка на площині”: координати, значення.
Варіант 10: Клас “Точка на площині екрана дисплея”: координати,
порядковий номер.
Варіант 11: Клас “учасник змагань”: країна, вид спорту, назва учасника.
Варіант 12: Клас “довге число”: значення, кількість знаків, основа
системи числення.
Варіант 13: Клас “Станція”: координати, назва .
Варіант 14: Клас “ істота ”: координати, вік, назва. Метод move –
збільшення кожної координати на одиницю.
Варіант 15: Клас “кліматичні умови”: температура. освітленість.
вологість, кислотність грунту.

22
Варіант 16: Клас “давач” (sensor): поточне значення, максимально і
мінімально допустимі, тип (t - температурний, p - тиску, І - освітленості, pH –
рівня кислотності), сигнал тривоги.
Варіант 17: Клас “товар на складі”: назва, кількість, розміщення .
Варіант 18: Клас “фраза”: вміст, кількість слів, кількість символів,
кількість різних символів алфавіту.
Варіант 19: Клас “число”: вміст, кількість цифр, основа системи
числення .
Варіант 20: Клас “коло”: x, y, R, ознака візуалізації (чи відображати на
екрані).
Варіант 21: Клас “книга”: код УДК, назва, автор, рік видання, кількість
сторінок.
Варіант 22: Клас “обладнання”: назва, вартість, дата виготовлення, група
(5, 15, 25 – амортизація) і клас “модернізація обладнання” (дата ремонту,
вартість ремонту).
Варіант 23: Клас “товар”: назва, виробник.
Варіант 24: Клас “банківський рахунок”: назва банку, номер рахунку,
МФО, вміст.
Варіант 25: Клас “підключення”: назва мережі, наявність пільги.

2.4 Порядок захисту


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

2.5 Контрольні запитання


1. Як визначається об’єкт у предметній області, у програмній реалізації? Чи
розрізняються поняття об’єкт, клас, екземпляр класу?
2. Що таке повідомлення, метод, поведінка об’єкта? Наведіть приклад опису
класу, визначення об’єкта і передачі повідомлення об’єкту в С++.
3. Для чого призначена діаграма класів (class diagram)? Назвіть її основні
елементи.
4. Дайте визначення класу. Які типи класів ви знаєте?
5. Що таке атрибути класу? Які типи атрибутів ви знаєте?
6. Що таке операції класу? Які типи операцій ви знаєте?

23
Лабораторна робота 3. Керуючі структури в С++.

Мета роботи: отримати навички використання операторів


розгалуження й операторів циклів у С/C++.

3.1 Ви навчитесь:
По завершенні цього розділу Ви будете вміти:
 користуватись операторами розгалуження
 аргументувати їх вибір
 в коді використовувати відповідний оператор циклу

3.2 Теоретичні відомості


3.2.1 Оператори розгалуження та переходу:
До операторів розгалуження та переходу відносять if, if else, switch, break,
continue, case і goto. Загальний вигляд простих операторів розгалуження такий:
if (логічний_вираз) оператор;

if (логічний_вираз) оператор_1;
else оператор_2;

Також використовують тернарну операцію умови:


логічний_вираз ? оператор_1 : оператор_2;
Якщо значення логічного виразу істинно, то виконується оператор_1, у
протилежному випадку виконується оператор_2.
Приклад 1. Знайти максимум з двох чисел x і у.
1 max=(x>y) ? x:у;
2 cout<<"max="<<max;

Операцію умови зручно використовувати у випадках вибору значення з


двох можливих. Вирази з використанням операції умови більш компактні — це
і є єдина перевага.

Оператор вибору switch є складним оператор розгалуження, що дозволяє


організувати вибір більше ніж, двох варіантів розгалуження:
switch (вираз_цілого_типу)
{ case значення_1: послідовність_операторів_1; break;
case значення_2: послідовність_операторів_2; break;
...
case значення_n: послідовність_операторів_n; break;
24
default: послідовність_операторів_n+1;
}

Гілку default можна не описувати. Вона виконується, якщо жодна з


попередніх умов не задовольняється.
Оператор break не є частиною оператора розгалуження. Він може
викликатись у будь якому блоці програми для примусового виходу з блоку
(break передає управління оператору, записаному після закриваючої фігурної
дужки } блоку).
Оператор continue повертає виконання програми на початок блоку.
Оператор goto є оператором безумовного переходу на мітку.

3.2.2 Оператор циклу


У С/C++ є такі конструкції, які дозволяють програмувати цикли: while, do
while і for.
Цикл із передумовою (перевіркою умови перед виконанням циклу)
while (логічний_вираз) оператор;
Цикл while перевіряє, чи логічний_вираз є істинним, і якщо так, то
виконує оператор поки значення логічного_виразу не зміниться. При виконанні
циклу з передумовою тіло циклу може не виконуватись ні разу, якщо умова з
самого початку дає результат "false" (0).

Цикл із післяумовою (перевіркою умови після виконання циклу)


do оператор;
while (логічний_вираз);
Цикл do… while виконує оператор поки умова (логічний_вираз) є
істинною. При виконанні циклу з післяумовою, на відміну від попередного,
тіло циклу обов’язково виконується хоча б один раз, навіть, якщо умова з
самого початку дає результат " false" (0).

Цикл із параметрами:
for (ініціалізація; перевірка; нове_значення) оператор;
Цикл із параметрами, може використовуватись у більшості випадків і
заміняти собою інші види циклів. Найпоширенішим є використання циклу for
тоді, коли потрібно змінювати значення цілого параметру від початкового до
кінцевого значення з певним кроком, наприклад, при індексуванні масивів:
1 for (i=0; i<n; i++) a[i]=0;

25
3.3 Порядок виконання
Розробити програму згідно умови, детально прокоментувати код:
1. Дано N цілих значень. Серед них знайти максимальне, мінімальне,
діапазон та середнє арифметичне (для всіх).
2. Розробити програму згідно варіанту:
1. На площині знаходиться коло з радіусом R і центром в початку координат.
Ввести задані координати точки і визначити, чи лежить вона на колі.
Вивести результат на екран. Розв'язати задачу при R=2 для точок з
координатами (0;2), (-1.5;0.7), (1;1), (3;0).
2. Дано натуральне число n. Отримати шістнадцяткове представлення цього
числа у вигляді послідовності символів (‘0’..’F’).
3. Для заданого цілого числа визначити а) чи кратне воно 3; а) чи кратне воно
9. Використати наступну властивість: якщо сума цифр числа кратна 3 (9), то
і число кратне 3 (9).
4. Дано діагональ куба. Знайти площу поверхні та об’єм куба.
5. Дано два дійсних числа. Знайти середнє арифметичне цих чисел та середнє
геометричне їх модулів.
6. Задано площу круга R та квадрата S. Визначити чи поміститься квадрат в
крузі. Розв'язати задачу для 1) R=70, S=36.74; 2) R=0.86, S=0.64.
7. Дано натуральне число n. Отримати вісімкове представлення цього числа у
вигляді послідовності символів (‘0’..’7’).
8. Для заданого цілого числа визначити: а) чи кратне воно 5;
б) чи кратне воно 2.
9. В ЕОМ вводиться дата: послідовно день, місяць, рік (цілі числа). Визначити
порядковий номер дня в році.
10. Задано координати двох точок. Визначити, чи лежать вони на одному колі з
центром в початку координат. Результат вивести на екран. Розв'язати задачу
для точок з координатами (0;2), (2;0), (1;3), (2;2).
11. Дано катети прямокутного трикутника, знайти його гіпотенузу та площу.
12. В ЕОМ вводиться дата: послідовно день, місяць, рік, день тижня, на який
припадає Новий рік (цілі числа). Визначити день тижня, на який припадає
вказана дата.
13. Дано натуральне число n. Отримати двійкове представлення цього числа у
вигляді послідовності символів (нулів і одиничок).
14. Визначити час падіння каменя з висоти h на поверхню землі.
15. Дано дійсне число x. Не користуючись ніякими іншими арифметичними
операціями, крім множення, додавання і віднімання, обчислити: 2x4–
3x3+4x2–5x+6. Дозволяється використовувати не більше чотирьох множень
і чотирьох додавань і віднімань.

26
16. Дано сторону рівностороннього трикутника. Знайти площу цього
трикутника.
17. Три резистори (опори) з’єднані паралельно, знайти опір з’єднання.
18. Скласти програму знаходження першого справа входження символу в даний
символьний рядок. В разі незнаходження результатом роботи має бути –1.
19. Дано символьний рядок s, в ньому не менше двох компонентів. Виявити чи
є дві перших компоненти цифрами.
20. Дано символи S1, . . . , Sn, “*”, “/”. Залишити послідовність S1. . . Sn без
змін, якщо в неї не входив символ “*”, інакше кожен символ “/”, який
передує першому входженню символу “*”, замінити на “.”.
21. Дано натуральне число n, символи s1, …, sn. Будемо розглядати слова,
розділені пробілами, які входять в послідовність s1, …, sn . Знайти яке-
небудь слово, яке починається буквою “A” і закінчується ”Z” (якщо таких
немає, то повідомити про це).
22. Дані символи S1 , …, Sn . Відомо, що символ S1 відмінний від крапки і, що
серед S2 , …, Sn є хоча б одна крапка. Нехай S2, …, Sm — передуючі
першій крапці (m наперед невідоме). Отримати послідовність послідовність
Sm , Sm-1 , …, S1 .
23. Дані символи S1 , …, Sn . Відомо, що символ S1 відмінний від крапки і, що
серед S2 , …, Sn є хоча б одна крапка. Нехай S2, …, Sm — передуючі
першій крапці (m наперед невідоме). Отримати послідовність S1 , S3 , …,
Sm , якщо m — непарне, або послідовність S2 , S4 , …, Sm , якщо m —
парне.
24. Данi натуральне число n i символи s1, …, sn . Замiнити всi знаки оклику
крапками.
25. Дано натуральне n, символи s[1],…s[n]. Кількість символів в кожному слові
до 15. Знайти слово, яке закінчується певною буквою (якщо таких слів
немає, то повідомити про це).
26. Дано символи S1, …, S33. Якщо послідовність S1, …, S33 така, що S1=S16,
S2=S17,…, то залишити її без змін, інакше отримати послідовність
S1, S2, …, S33, S1, S2, …, S33.
27. Дано натуральне число n, символи S1, . . . , Sn . Замінити в послідовності
S1, . . . , Sn кожну групу букв “child” групою “children”.
28. Задано натуральне число n, і символи s1, ..., sn. Будемо вважати, що слова,
утворені символами послідовності s1, ..., sn, мають довжину не більше 15
символів. Видалити з s1, ..., sn всі слова з непарними порядковими
номерами і перевернути всі слова з парними порядковими номерами.
29. Задано натуральне число n, і символи s1, ..., sn та символ k. Створити
послідовність символів ss1, ..., ssn, де кожен ssi рівний результату логічної
операції “виключне або” між si та k. Створити послідовність символів
27
sss1, ..., sssn, де кожен sssi рівний результату логічної операції “виключне
або” між ssi та k. Вивести послідовності ss1, ..., ssn та sss1, ..., sssn.
30. Дано натуральні числа k, m, n, символи s1..sk, t1..tm, u1..un. Отримати по
одному разу ті символи, які входять одночасно в усі три послідовності.

3.4 Порядок захисту


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

3.5 Контрольні запитання


1. Які форми запису має умовний оператор if?
2. Назвіть відмінні особливості операції умови в порівнянні з умовним
оператором.
3. Для вирішення яких задач зручно використовувати оператор switch?
4. Назвіть керуючі оператори в циклах.
5. Які три операції виконуються в циклі fоr?
6. Що таке вкладені цикли?

28
Лабораторна робота 4. Робота з вказівниками. Опрацювання масивів

Мета роботи: отримати навички роботи з одно- та багатовимірними


масивам. Навчитися розуміти і використовувати вказівники при створенні
програм на С / С++.

4.1 Ви навчитесь:
По завершенні цього розділу Ви будете вміти:
 описати основні відмінності між вказівниками та посиланнями
 працювати з динамічними та статичними масивами

4.2 Теоретичні відомості


На машинному рівні імена змінних у командах не використовуються, а
тільки адреси, сформовані транслятором з використанням імен змінних. Проте
програміст не має доступу до цих адрес, якщо він не використовує вказівники.
У мові С++ є операція визначення адреси— &, за допомогою якої
визначаються адреса комірки пам’яті, що містить задану змінну. Наприклад,
якщо vr — ім’я змінної, то &vr— адреса цієї змінної. У С++ також існують і
змінні типу вказівник.
4.2.1 Вказівник
Вказівник (покажчик) — це змінна або константа стандартного типу
даних для збереження адреси змінної визначеного типу. Значення вказівника –
це беззнакове ціле, воно повідомляє, де розміщена змінна, і нічого не говорить
про саму змінну.
Тип змінної, що адресується, може бути стандартний, нумерований,
структурний, об'єднання або void.
Значення змінної-вказівника – це адреса деякої величини, ціле без знака.
Вказівник містить адресу першого байту змінної визначеного типу. Тип
змінної, що адресується, і на яку посилається покажчик, визначає об’єм
оперативної пам’яті, що виділяється змінній, та зв'язаному з нею покажчикові.
Опис таких змінних здійснюється за допомогою наступних виразів:
<тип> *<ім'я вказівника на змінну заданого типу>;
Приклади опису вказівників:
1 int* ptri; //вказівник на змінну цілого типу
2 char* ptrc; //вказівник на змінну символьного типу
3 float* ptrf;//вказівник на змінну з плаваючою крапкою

29
Нехай змінна-вказівник має ім'я ptr(тобто оголошена як int* ptr), тоді в
якості значення їй можна присвоїти адресу за допомогою наступного
оператора:
ptr=&vr;

У мові С++ при роботі з вказівниками велике значення має операція


непрямої адресації (розіменування вказівника) — *. Операція * дозволяє
звертатися до змінної не напряму, а через вказівник, який містить адресу цієї
змінної. Ця операція є унарною і має асоціативність зліва на право. Цю
операцію не слід плутати з бінарною операцією множення. Нехай ptr —
вказівник, тоді *ptr— це значення змінної, на яку вказує ptr.
Для вищенаведеного прикладу:
1 int *ptr; // оголошення змінної типу вказівник
2 *ptr=1; // розіменування вказівника(значення
3 //змінноїvr, на яку вказує вказівник)

Операція * у деякому розумінні є оберненою до операції &. Розглянемо


приклад роботи з вказівниками та посиланнями[1]:
1 int a = 1, b;
2 int* ptr = &a; //містить адресу змінноїa
3 cout << “ Зміннаa = ” << (*ptr);
4 cout << “зберігається за адресою” << ptr;
5 b = ptr;
6 //помилка: вказівник не перетворюється у ціле число
7 b = *ptr + 1; // b = 2

4.2.2 Посилання
Посилання(reference) — це видозмінена форма вказівника, що може
використовуватись як псевдонім (інше ім’я) змінної. Тому посилання не
потребують додаткової пам’яті. Для визначення посилання використовують
символ &(амперсант), який ставиться перед змінною-посиланням.
1 #include <iostream>
2 using namespace std;
3 int main()
4{
5 int t = 13,
6 int &r = t;// ініціалізація посилання на t
7 // тепер r синонім імені t
8 cout << "Початкове значенняt:" << t;
9 // виводить13
10 r += 10; // зміна значення t через посилання
11 cout<<"\n Остаточне значенняt:" << t;
12 // виводить 23
13 return 0;

30
14 }

У даному випадку посилання використовувалось в якості псевдоніму


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

4.2.3 Масив
Масив являє собою набір однотипних об’єктів, які мають спільне ім’я і
відрізняються місцезнаходженням в цьому наборі (або індексом, присвоєним
кожному елементу масиву). Елементи масиву займають одну неперервну
область пам’яті комп’ютера і розміщені послідовно один за одним.
1 double mas2[250];// масив з 250 чисел типу double
2 static char mas3[20];//статичний рядок з 20 символів
3 extern masl[];//зовнішній масив, розмір вказаний вище
4 int mas4[2][4]; // двовимірний масив з чисел типу int

Нумерація елементів масиву починається з нуля і закінчується n-1, де n -


кількість елементів масиву.
Ініціалізація масиву означає присвоєння початкових значень його
елементам при оголошенні. Масиви можна ініціалізувати списком значень або
виразів, відокремлених комою, розташованих у фігурних дужках.
1 int days[12]={31,28,31,30,31,30,31,31,30,31,30,31};

Якщо список значень, які ініціалізуються, коротший за довжину масиву,


то ініціалізації підлягають перші елементи масиву, а решта ініціалізуються
нулем. Масив також можна ініціалізувати списком без зазначення в дужках
довжини масиву. При цьому масиву присвоюється довжина за кількістю
ініціалізаторів.
Приклад 3. Визначення довжини масиву при ініціалізації.
1 char code[] = {'a', 'b', 'c'};

Взагалі кажучи, ім’я масиву є константним вказівником, який


ініціалізовано базовою адресою [1]. Таким чином, масиви і вказівники
використовуються для однієї мети: доступу до пам’яті. Різниця полягає в тому,
що вказівник є змінною, яка приймає в якості значення адресу комірки пам’яті.
А ім’я масиву може розглядатися як константний вказівник з
фіксованою(базовою) адресою [1].
1 int mas[4];
2 int* ptr = mas;

31
Адреса &mas[0] &mas[1] &mas[2] &mas[3] або
або ptr або ptr+1 або ptr+2 ptr+3
Значення mas[0] або mas[1] або mas[2] або mas[3] або
*ptr *(ptr+1) *(ptr+2) *(ptr+3)

Таким чином, в даному випадку записи ptr+i та &mas[i] рівносильні, де i —


деяке зміщення (ціле число) від адреси ptr або &mas (в даному випадку i=0..3).
Відмінність полягає в тому, що значення ptr+i змінювати можна, а &mas[i]—
ні.
Для отримання значення елементу масиву через вказівник ptr необхідно
використати операцію розіменування.
1 const int N = 10;
2 int mas[N];
3 int* ptr = mas; // абоptr = &mas[0]
4 // 1 варіант: через вказівник ptr
5 int sum1 = 0;
6 for (ptr = mas; ptr < &mas[N]; ++ptr)
7 sum1 += *ptr;
8 // 2 варіант: з використанням індексів
9 int sum2 = 0;
10 for (int i = 0; i < N; ++i)
11 sum2 += mas[i];
12 // рівносильноsum2 += *(mas + i);

Аналогічна адресна арифметика використовується при використанні масивів


більшої розмірності.

4.2.4 Динамічні масиви


Динамічним називається масив, розмірність якого стає відомою в процесі
виконання програми.
В С++ для роботи з динамічними об’єктами використовують спеціальні
оператори new та delete. Ці оператори використовуються для керування
вільною пам’яттю. Вільна пам’ять(або купа, heap) — це область пам’яті, яка
надається системою для розміщення об’єктів, час життя яких напряму
керується програмістом [1]. За допомогою оператора new виділяється пам’ять
під динамічний об’єкт(який створюється в процесі виконання програми), а за
допомогою оператора delete створений об’єкт видаляється з пам’яті. Оператор
new має наступнимй синтаксис.
new ім’я_типу;
new ім’я_типу ініціалізатор;
new ім’я_типу[вираз];

32
В результаті виконання оператору new в пам’яті виділяється об’єм пам’яті,
який необхідний для зберігання вказаного типу, і повертається базова адреса.
Якщо пам’ять недоступна, оператор new повертає значення 0, або генерує
виняткову ситуацію.
Оператор delete має наступний формат:
delete вираз;
delete[] вираз;

Розглянемо виділення пам’яті під динамічний масив. Нехай розмірність


динамічного масиву вводиться з клавіатури. Спочатку необхідно виділити
пам’ять під цей масив, а потім створений динамічний масив необхідно
вилучити з пам’яті. Це можна зробити наступним чином.
1 int n; // n — розмірність масиву
2 cin >> n; // вводимо з клавіатури
3 int* mas = new int[n];
4 // виділення пам’яті під динамічний масив
5 delete[] mas; // звільнення пам’яті

Зауваження!
Завжди використовуйте оператор delete після виділення пам’яті за допомогою
оператора new. Це входить в обов’язки програміста! Інакше це може
призвести до втрати пам’яті.

Аналогічно до одновимірних масивів задаються двовимірні, тривимірні і


т. д. Багатовимірний масив можна уявляти як масив масивів. Наприклад,
двовимірний масив (матриця) є одновимірним масивом, елементами якого є
одновимірні масиви:

4.3 Порядок виконання


Розробити програму згідно варіанту (для статичного та динамічного
масивів), детально прокоментувати код:

1. Вивести введені з клавіатури числа з плаваючою комою в зворотньому


порядку, використовуючи вказівники.
2. Створити вказівник на масив типу double довжиною n з допомогою
процедур динамічного виділення і знайти максимальне значення в
отриманому масиві. При виділенні пам’яті перевірити його коректність.

33
3. Створити квадратну матрицю (двовимірний масив чисел) у вигляді масиву
вказівників на одновимірні масиви — рядки матриці. Обчислити суму
головної діагоналі отриманої матриці.
4. З клавіатури послідовно вводяться n символів, серед яких обов’язково є
декілька пробілів. Символи заносяться в чергу, поки не буде введено
пропуск. Введене слово виводиться в новому рядку, після чого
продовжується ввід символів з наступного рядка. Ввід символів
припиняється, коли досягнуто кінець масиву, в якому зберігається черга.
5. Знайти у заданій послідовності символів співпадання з ключовим словом,
заданим, як вказівник на константу.
6. Заданий масив чисел з плаваючою комою та вказівник на нього.
Перемістити вказівник на перше число у масиві, що співпадає із заданою
константою.
7. Записати введені з клавіатури числа з плаваючою комою в чергу. Вилучити
іх послідовно з черги і вивести на екран, якщо відповідний елемент —
додатне число.
8. Скласти програму, що створює чергу, яка містить всі числа від 300 до 600,
що діляться на 6. Вивести ці числа на екран в порядку зростання.
9. Задано масив чисел з плаваючою комою, серед яких багато нульових
елементів. Створити масив, що містить вказівники на ненульові елементи.
10.Задано рядкову змінну, що містить послідовність символів, серед яких є
цифри. Скласти програму, що перетворює цю змінну в десяткове число,
вилучаючи символи, що не є цифрами. Число формувати, починаючи з
молодшого розряду.
11.З клавіатури послідовно вводяться слова. Якщо слово співпадає з першим
словом у черзі, то воно видаляється із черги, якщо ні — то додається до
неї. Ввід припиняється, при введенні слова “STOP”. Після цього отримана
черга виводиться на екран.
12.З клавіатури послідовно вводиться n символів, серед яких обов’язково є
декілька пробілів. Вивести введені символи в зворотньому порядку, при
цьому вилучити всі пропуски.
13.Скопіювати всі від’ємні числа з масиву A в масив B, в зворотньому
порядку використовуючи вказівники.
14.З клавіатури послідовно вводяться числа типу short. Скласти програму, яка
виводить спочатку додатні числа в порядку їх введення, а потім від’ємні в
порядку їх введення. Використати чергу. Ввід чисел припиняється, коли
введене число — 0.
15.Відсортувати за спаданням масив цілих чисел а0, …, аn-1. обмінним
сортуванням з використанням вказівників. Відсортований масив

34
формується систематичним обміном елемента з номером i та
максимального елемента послідовності аi+1, …, аn-1, i=0, 1, … n-2.
16.Замінити в масиві чисел типу long int всі додатні числа найменшим
від’ємним числом, використовуючи вказівники.
17.Задано масив чисел, серед яких багато нульових елементів. Створити
масив, що містить вказівники на ненульові елементи, та інший масив, що
містить вказівники на ті елементи масиву вказівників, які вказують на
додатні числа.
18.Задано дві рядкові змінні, що містять по декілька слів, розділених
пробілами. Використовуючи вказівники, визначити, чи є у цих змінних
спільні слова, і якщо є, то вивести їх на екран.
19.Зашифрувати з використанням вказівників задану рядкову змінну обміном
символів з непарними та парними номерами. Вивести зашифровану
послідовність.
20.Створити вказівник на масив символів довжиною n з допомогою процедур
динамічного виділення і вивести всі десяткові цифри, що знаходяться в
отриманому масиві. При виділенні пам’яті перевірити його коректність.
21.Задано дві рядкові змінні. Вивести на екран спільні послідовності не
коротші 5 символів, що зустічаються у цих змінних, використовуючи
вказівники.
22.З допомогою вказівників розшифруйте текстове повідомлення, яке
зашифроване в рядковій змінній, що містить букви і цифри. Алгоритм
розшифрування: послідовно, починаючи від першого аналізуються
символи. Якщо символ — буква, то він береться без змін, якщо — цифра
від 1 до 9, то перескакуємо на стільки символів уперед.
23.Зашифрувати задану рядкову змінну з допомогою операції “виключне або”
(^) із заданим ключем у вигляді послідовності символів. Вивести
зашифровану послідовність, та результат повторного її шифрування з тим
же ключем.
24.З клавіатури послідовно вводяться слова. Ввід слів припиняється і
видається попереджувальне повідомлення, якщо слово співпадає з одним із
раніше введених слів.
25.Нехай дано масив чисел а 1 …а n . Сформувати масив вказівників на
елементи цього масиву, в якому числа, на які вказують вказівники,
впорядковані за зростанням.
26.Задано рядкову змінну, що містить цифри і букви. Створити масив
вказівників, що вказують на початок кожної послідовності в даній рядковій
змінні, що складається виключно з цифр.

35
27.Замінити в масиві чисел типу unsigned char всі послідовності з трьох і
більше нулів елементом, що йде після цієї послідовності нулів. Для
знаходження довжини послідовності нулів використати різницю між
вказівниками на початок і кінець цієї послідовності.
28.Створити вказівник на масив цілого типу довжиною n з допомогою
процедур динамічного виділення і знайти кількість від’ємних елементів в
отриманому масиві. При виділенні пам’яті перевірити його коректність.
29.Відсортувати за зростанням масив чисел з плаваючою комою обмінним
сортуванням з використанням вказівників. Відсортований масив
формується систематичним обміном двох суміжних елементів, що не
відповідають порядку зростання, доки такі пари існують.

4.4 Порядок захисту


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

4.5 Контрольні запитання


1. Що таке вказівник? Як він використовується? Який сенс операції
розіменування?
2. Як оголошується змінна типу вказівник?
3. Чому при оголошенні вказівника необхідно вказувати тип змінної, яка
адресується за його допомогою?
4. Що таке посилання? Яка область застосувань посилань? Яке значення
операції &?
5. Як співвідносяться вказівники та посилання?
6. Що таке масив? Дайте визначення.
7. В чому переваги представлення інформації у вигляді масиву?

36
Лабораторна робота 5. Функції. Шаблони функцій

Мета роботи: отримати навички роботи з функціями та шаблонами


функцій.

5.1 Ви навчитесь:
По завершенні цього розділу Ви будете вміти:
 працювати з функціями та шаблонами функцій
 використовувати рекурсивні функції

5.2 Теоретичні відомості


Кожна програма у своєму складі повинна мати головну функцію main().
Саме функція main() забезпечує точку входу (початок виконання) в об’єктний
модуль. Взагалі, функція — це іменована частина програмного коду, що, як
правило, призначена для виконання визначених дій в межах програми.
Крім функції main(), в програму може входити будь-яка кількість
функцій. Кожна функція по відношенню до іншої є зовнішньою. Для того, щоб
функція була доступна, необхідно, щоб до її виклику про неї було відомо
компілятору.

З поняттям функції у мові С++ пов’язано три наступних терміна:


 опис функції;
 прототип функції;
 виклик функції.

Опис функції складається з двох частин: заголовка та тіла. Опис функції


має наступну форму запису:
/* заголовок функції*/
[тип_ результату] <ім’я>([список_параметрів])
{
/* оголошення і оператори*/
тіло_функції
}

Тип результату — це тип значення, яке може повертати функція. При


відсутності специфікатора типу передбачається, що функція повертає ціле
значення (int). Якщо функція не повертає ніякого значення, то на місці типу
записується специфікатор void. У списку параметрів для кожного параметра
37
повинен бути зазначений тип. При відсутності параметрів список може бути
порожнім або мати специфікатор void.
Тіло функції — це послідовність оголошень і операторів, які описують
визначений алгоритм. Важливим оператором тіла функції є оператор
повернення в точку виклику: return [вираз]. Оператор return має подвійне
призначення. Він забезпечує негайне повернення у зовнішню функцію і може
використовуватися для передачі обчисленого у функції значення. У тілі функції
може бути декілька операторів return, але може не бути й жодного. В
останньому випадку повернення у місце виклику буде здійснено після
виконання останнього оператора тіла функції.
Прототип функції може вказуватися до виклику функції замість опису
функції для того, щоб компілятор міг виконати перевірку відповідності типів
аргументів і параметрів. Прототип функції за синтаксисом подібний заголовку
функції, але наприкінці його ставиться крапка з комою ;. Параметри функції в
прототипі можуть мати імена, які не є обов’язковими.
Компілятор використовує прототип функції для порівняння типів
аргументів з типами параметрів. Мова С++ не передбачає автоматичного
перетворення типів у випадках, коли аргументи не співпадають за типами з
відповідними їм параметрами. Тобто мова С++ забезпечує строгий контроль
типів.
Виклик функції може бути оформлений у вигляді
ім'я_функції(список_аргументів);
Кількість і типи формальних аргументів повинні співпадати з кількістю і
типом фактичних параметрів функції. При виклику функції фактичні параметри
підставляються замість формальних аргументів.

5.2.1 Передача аргументів за замовчуванням


Значення формальних параметрів можуть бути задані за замовчуванням.
Зазвичай це константа, яка часто використовується при виклику функції. При
цьому при описі функції перелік параметрів за замовчуванням повинен
міститися в кінці списку формальних змінних функції. Нижче наведено
декілька прикладів:
1 void foo(int i = 3, int j); // некоректно
2 void foo(int i, int j = 7, int k = 8); // коректно
3 void foo(int i = 1, int j = 7, int k = 8); коректно
4 void foo(int i, int j = 7, int k); // некоректно

5.2.2 Вбудовані та перевантажені функції


Зазвичай вибір імені функції повинен відобразити її основне призначення.
Механізм перевантаження дозволяє використовувати одне ім’я для декількох

38
функцій. Вибір конкретної реалізації залежить від типу аргументів функції.
Наприклад:
1 int max(int, int);
2 double max(double, double);

Вбудовані функції в С++ визначаються за допомогою ключового слова


inline. Воно розташовується перед оголошенням функції, коли необхідно, щоб
код в тілі функції вбудовувався в місце виклику функції [1].
1 inline double cube (double x)
2 {
3 return (x*x*x);
4 }

Обмеження компілятора не дозволяють вбудовувати складні функції.


Крім того, ключове слово inline є лише рекомендацією компілятору.

5.2.3 Рекурсивні функції


В інженерній практиці доводитися часто реалізовувати рекурсивні
алгоритми. Така необхідність виникає при роботі з динамічними структурами
даних, таких як стеки, дерева, черги, тощо. Для реалізації рекурсивних
алгоритмів у С++ передбачена можливість створення рекурсивних функцій.
Рекурсивна функція — це функція, у тілі якої здійснюється виклик цієї ж
функції.
1 //Програма для обчислення факторіала числа
2 #include <iostream.h>
3 int fact(int n);
4 int main()
5{
6 int m;
7 cout << "\nВведіть ціле число:";
8 cin >> m;
9 cout << "\n Факторіал числа" << m;
10 cout << "дорівнює" << fact(m);
11 return 0;
12 }
13 int fact(int n)
14 {
15 int a;
16 if (n<0) return 0;
17 if (n==0) return 1;
18 a =n * fact(n-1); // виклик цієї ж функції для n-1
19 return a;
20 }

39
Для від’ємного аргументу факторіала не існує, тому функція в цьому
випадку повертає нульове значення. Оскільки за означенням факторіал нуля
дорівнює 1, то в тілі функції передбачений і цей варіант. У випадку, коли
аргумент функції fact() відмінний від 0 та 1, функцію fact() викликається із
зменшеним на одиницю значенням параметра, а результат множиться на
значення поточного параметра. Таким чином, в результаті вбудованих викликів
функцій буде отримано наступний результат:
n * (n-l) * (n-2) * ... * 2 * 1 * 1

5.2.4 Шаблони функцій


Шаблон є схематичним описом побудови функцій. Використовуючи
шаблони, з’являється можливість створювати узагальнені специфікації
функцій, що найчастіше носять назву параметризованих функцій (generic
functions). Таким чином, за допомогою реалізації узагальнених функцій можна
зменшити розмір та складність програми.
Шаблон функції декларується за допомогою ключового слова template.
Це слово використовується для створення шаблону (каркасу), що в загальних
рисах описує призначення функції та надає опис операцій – сутність алгоритму,
що може застосовуватися до даних різних типів. При цьому конкретний тип
даних, над яким функція повинна виконувати операції, передаватиметься їй на
етапі компіляції. Загальна форма функції-шаблону має вигляд:
temрlate <список_аргументів_шаблону> тип
ім’я_функції(параметри)
{
// тіло функції
}
Список аргументів шаблону складається з ключового слова class та
ідентифікатору (-ів), що визначає його тип. Коли компілятор створюватиме
конкретну версію цієї функції, він автоматично замінить цей параметр
конкретним типом даних. Цей процес носить назву інстанціювання шаблону.
Зручним є створення прототипу шаблона функції у вигляді його
попереднього оголошення. Таке оголошення інформує компілятор про
наявність шаблону та його очікуваних параметрах, наприклад:
template <class T> void funk(T array[ ], sizearray);

Нижче наведений приклад використання параметризованої функції


swap(T& x, T& y), що здійснює обмін значеннями між двома її параметрами:

1 #include <stdio>
2 template <class T> void swap(T& x, T& y);

40
3 int main()
4 {
5 int a=5,b=10;
6 float c=7,d=14;
7 char ch='a',chh='A';
8 swap(a,b); // виклик для цілих аргументів
9 printf("a=%d, b=%d\n",a,b);
10 swap <float>(c,d); // виклик для float аргументів
11 printf("c=%f, d=%f\n",c,d);
12 swap <char>(ch,chh); // виклик для char аргументів
13 printf("ch=%c, chh=%c\n",ch,chh);
14 return 0;
15 }
16
17 // визначення параметризованої функції
18 template <class T> void swap(T& x, T& y)
19 {
20 T temp=x;
21 x=y;
22 y=temp;
23 }

Програма відкривається прототипом шаблонної функції. Аналізуючи


приклад, зауважимо, що для інстанціювання шаблону застосовуються дві
форми.
Конкретний тип для цього визначається компілятором автоматично,
виходячи з типів параметрів у місці виклику функції (у наведеному вище
прикладі це тип int), або задається явним способом (у прикладі це підстановка
типів float та char).
Якби swap() була звичайною функцією, то потрібною була б її реалізація.
Оскільки це шаблонна функція, компілятор сам реалізуватиме код такої
функції, замінивши у даному випадку тип Swap на int, float та char. Таким
чином можна зменшити розмір та складність програми, запропонувавши
компілятору реалізацію узагальнених функцій.

5.3 Порядок виконання


Розробити програму згідно варіанту (реалізувати два випадки, звичайну
функцію та шаблон функції), детально прокоментувати код:

1. Написати варіанти функції знаходження найменшого спільного


кратного (НСК) з передачею обчислених значень через параметри-
вказівники і через зовнішні змінні. Функція за цілими значеннями a,

41
b обчислює їхнє найменше спільне кратне НСК(a, b) та числа c і d
такі, що ac=bd=НСК(a, b).
2. Написати варіанти функції з передачею обчислених значень через
параметри-вказівники і через зовнішні змінні, коли функція за
трьома дійсними числами, що задають сторони трикутника,
обчислює його площу і периметр.
3. Написати варіанти функції з передачею обчислених значень через
параметри–вказівники і через зовнішні змінні, коли функція за
цілим n>7 розраховує цілі a, b такі що 5a+3b=n, a+b є мінімальним.
4. Дано натуральне число n. Нехай n!! означає 1*3*5*…n для
непарного n, і 2*4*6*…n — для парного n. Написати варіанти
функції, що обчислює n!! та (-1)n+1 n!!, з передачею обчислених
значень через параметри-вказівники і через зовнішні змінні.
5. Написати варіанти функції, що обчислює для заданого
натурального числа n значення n!+n та 2n!, з передачею обчислених
значень через параметри-вказівники і через зовнішні змінні.
6. Для заданого натурального числа n обчислити суму послідовності
чисел 20, 21, 22, …, 2n-1, використовуючи варіанти функції з
передачею обчислених значень через параметри-вказівники і через
зовнішні змінні.
7. Написати функцію, що для квадратного рівняння із заданими
коефіцієнтами, повертає значення детермінанта та обчислює корені
квадратного рівняння із заданими коефіцієнтами і повертає їх за
допомогою параметрів-вказівників та через зовнішні змінні.
8. Написати функцію, що обчислює мінімальне, середнє арифметичне
та максимальне значення для заданих у вигляді її арґументів трьох
чисел. Всі три обчислені значення потрібно повернути іншими
способами.
9. Написати функцію, яка повертає кількість повних років, місяців,
днів, годин, хвилин та секунд для заданого у секундах проміжку
часу.
10.Написати функцію, що для заданого натурального числа n повертає
три значення: кількість чисел у послідовності 1, 2,…, n, кратних 2, 3
та 5.
11.Дано дійсні числа c1, d1, c2, d2, що задають дійсні і уявні частини
комплексних чисел c1+id1, c2+id2. Написати функцію, що
знаходить добуток цих двох комплексних чисел і повертає значення
модуля отриманого комплексного числа, його фазу передає через
зовнішню змінну, а його дійсну і уявну частину — через параметри-
вказівники.
42
12.Дано дійсні числа c1, d1, c2, d2, що задають дійсні і уявні частини
комплексних чисел c1+id1, c2+id2. Написати функцію, що
знаходить суму цих двох комплексних чисел і повертає значення
модуля отриманого комплексного числа, його уявну частину
передає через зовнішню змінну, а його дійсну частину і фазу —
через параметри-вказівники.
13.Дано дійсні числа c1, d1, c2, d2, що задають дійсні і уявні частини
комплексних чисел c1+id1, c2+id2. Написати функцію, що
знаходить відношення цих двох комплексних чисел і повертає
значення модуля отриманого комплексного числа, його дійсну
частину передає через зовнішню змінну, а його уявну частину і
фазу — через параметри-вказівники.
14.Дано дійсні числа c1, d1, c2, d2, що задають дійсні і уявні частини
комплексних чисел c1+id1, c2+id2. Написати функцію, що
знаходить різницю цих двох комплексних чисел і повертає
значення модуля отриманого комплексного числа, його дійсну і
уявну частину передає через зовнішні змінні, а його фазу — через
параметр-вказівник.
15.Дано вісім чисел x1, y1, x2, y2,…, x4, y4, що задають координати
вершин чотирикутника. Написати функцію, що повертає його
периметр і площу через зовнішні змінні.
16.Дано вісім чисел x1, y1, x2, y2,…, x4, y4, що задають координати
вершин чотирикутника. Написати функцію, що повертає довжини
його діагоналей через параметри-вказівники.
17.Дано шість чисел x1, y1, x2, y2,…, x3, y3, що задають координати
вершин трикутника. Написати функцію, що повертає довжини його
медіан через параметри-вказівники.
18.Дано два числа r, h, що задають радіус основи і висоту прямого
кругового циліндра. Написати функцію, що повертає значення його
об’єму та площу його бокової поверхні через зовнішні змінні.
19.Дано два числа l, h, що задають твірну і висоту прямого кругового
конуса. Написати функцію, що повертає значення його об’єму та
площу його бокової поверхні через параметри-вказівники.
20.Дано три числа w, l, h, що задають сторони прямокутного
паралелепіпеда. Написати функцію, що повертає значення його
об’єму та площу його бокової поверхні через зовнішні змінні.
21.Дано два число r, що задає радіус кулі. Написати функцію, що
повертає значення її об’єму та площі через параметр-вказівник і
зовнішню змінну.

43
22.Написати функцію, що переводить значення декартових координат,
заданих через параметри-вказівники, у полярні.
23.Написати функцію, що переводить значення полярних координат,
заданих через зовнішні змінні, у декартові.
24.Написати варіанти функції, що переводить значення кута в
радіанах, заданого через параметр-вказівник і через зовнішню
змінну, у значення кута в градусах.

5.4 Порядок захисту


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

5.5 Контрольні запитання


1. Поясніть значення прототипу функції.
2. Який зв’язок між параметрами функції і аргументами? Поясніть механізм
передачі аргументів за значенням.
3. Яким чином можна забезпечити отримання за допомогою функції
декількох результатів?
4. Які змінні називаються глобальними?
5. У чому відмінність глобальних та локальних змінних?
6. Поясніть призначення різних класів пам’яті.
7. Наведіть означення рекурсивної функції та приклад їх застосування.
8. Наведіть приклад перевантаження функції.
9. У чому перевага використання вбудованих функцій?
10.Які правила використання аргументів за замовчуванням?

44
Лабораторна робота 6. Робота з класами. Реалізація принципу
інкапсуляції. Конструктори та деструктори

Мета роботи: вивчити реалізацію основних принципів об’єктно-


орієнтованого програмування на мові C++.

6.1 Ви навчитесь:
По завершенні цього розділу Ви будете вміти:
 створювати класи, об’єкти
 реалізовувати основні принципи ООП
 пояснити реалізацію конструкторів та деструкторів

6.2 Теоретичні відомості


ООП — парадигма програмування,в основу якої покладено принципи
інкапсуляції (encapsulation), наслідування (inheritance), поліморфізму
(polymorphism) — три ключові принципи ООП —та у якій центральними
поняттями є клас (class) та об’єкт (object). Також можна зустріти підходи, які
включають у визначення ООП крім трьох згаданих принципів ще три:
абстракція (abstraction), пересилка повідомлень (messaging) та модульність
(modularity).
Метод об’єктно-орієнтованого моделювання передбачає послідовне
виконання двох етапів: об’єктно-орієнтованого аналізу та об’єктно-
орієнтованого проектування. Тому термін “об’єктно-орієнтоване моделювання”
еквівалентний терміну “об’єктно-орієнтований аналіз і проектування” (ООАіП).
Аналіз – широке поняття. Його зміст детальніше відображають терміни
аналіз системних вимог (тобто дослідження вимог до майбутньої програмної
системи) та об’єктний аналіз (тобто дослідження об’єктів предметної області).
При цьому під предметною областю розуміють ту частину реального
світу, що має істотне значення чи безпосереднє відношення до процесу
функціонування програми. Іншими словами: предметна область містить у собі
тільки ті об’єкти і взаємозв’язки між ними, які необхідні для опису вимог і
умов розв’язання деякої задачі.
У процесі проектування головну увагу звертають на концептуальні
рішення, які забезпечують виконання системних вимог, а не на питання
реалізації. У процесі об’єктно-орієнтованого проектування визначають
програмні об’єкти та способи їхньої взаємодії/або схеми баз даних.
У результаті аналізу, зазвичай, оформляють словник (або глосарій)
предметної області (містить текстовий опис термінів, сутностей, користувачів
45
тощо) і технічне завдання, у якому сформульовано функціональні та
нефункціональні вимоги до системи. До нефункціональних вимог зачислено
питання надійності, зручності використання, продуктивності, можливості
супроводу програм, питання безпеки, проектні та апаратні обмеження тощо.
Отже, для подальшого коректного розуміння понять ООП формалізуємо
визначення понять :
Клас (class) — це тип (структура даних), що описує внутрішнє
влаштування об’єктів (реальних об’єктів) та способи їх взаємодії із оточуючим
середовищем (програмним середовищем). Клас, по суті, є програмною моделлю
об’єктів реального світу.
Об’єкт (object), або екземпляр класу, або інстанція (instance) —
сутність, що існує і функціонує у адресному просторі обчислювальної системи
та є фактичною реалізацією класу із конкретними значеннями параметрів та
характеристик, передбачених даним класом.
Інкапсуляція (encapsulation) — властивість системи, що дозволяє
поєднати дані і методи роботи з ними, приховавши деталі реалізації від
користувача. При цьому методи та дані класу, що залишаються доступними
для безпосереднього використання користувачем, називають інтерфейсними
або, у сукупності, інтерфейсом класу. Дані, що описують клас, називають, як
правило, його атрибутами чи полями, а функції, що описують методи обробки
цих даних, називають операціями або методами.
Ключовим поняттям в об’єктно-орієнтованому програмуванні на С++ є
поняття класу.
Клас в С++ – це практична реалізація абстрактного типу даних засобами
мови програмування С++ [1]. Фактично клас – це визначений програмістом
нестандартний тип даних, тому поняття полів і методів класу повністю
співпадають з аналогічними поняттями абстрактного типу даних. Процес
визначення класу складається з двох частин.
Перша частина – це опис класу. В цій частині визначається структура
класу, а саме кількість та типи полів (властивостей) класу, кількість методів,
кількість та типи вхідних параметрів методів, а також типи результатів
виконання методів. Крім того на цьому етапі визначається область видимості
полів та методів.
Опис класу починається з ключового слова class, за яким слідує назва
класу. Він складається з розділів, які виділяються модифікаторами public,
private, protected, що є заголовками розділів і визначають їх початок та область
видимості полів та методів, розташованих у розділі.
Опис класу обмежується заголовком класу та фігурними дужками „{”,
„}”. Перший розділ опису класу може бути без заголовку. В цьому випадку
вважається, що заголовком розділу є модифікатор private.
46
Друга частина визначення класу – це опис методів класу. В цій частині
реалізуються засобами мови програмування алгоритми методів класу.
Обидві частини є обов’язковими при визначенні класу і жодна з них не
може бути пропущена. Опис класу та опис методів класу повинні бути
розміщені у одному файлі. Зазвичай їх розміщують у окремих файлах із
розширенням „h” і потім включають за допомогою директиви #include до
кожного з тих файлів проекту, в яких використовуються об’єкти даного класу.
Опис класу (файл MyClass.h)
1 class MyClass
2 {
3 int i; //розділ із типом доступу private
4 public: //розділ із типом доступу public
5 int get_i();
6 void set_i(int);
7 };

Опис методів класу (файл MyClass.cpp):


1 #include "MyClass.h"
2 int MyClass::get_i() { return i; }
3 void MyClass::set_i(int x) { i=x; return; }
4 int main() {
5 return 0;
6 }

Як було сказано вище, клас – це абстрактний тип даних. Для того щоб
використати розроблений клас у програмі необхідно оголосити змінну даного
типу. Така змінна буде називатись об’єктом даного класу. Таким чином об’єкт
класу – це конкретна змінна (екземпляр) класу (даного типу інформаційної
структури).
Оголосити об’єкт даного класу можна таким же чином, як і змінну будь-
якого іншого стандартного або заданого користувачем типу. Наприклад,
оголосити об’єкт наведеного вище класу MyClass при умові, що даний клас
описаний у файлі MyClass.h, який знаходиться у одному каталозі з проектом,
можна наступним чином:
1 #include "MyClass.h"
2 int MyClass::get_i() { return i; }
3 void MyClass::set_i(int x) { i=x; return; }
4 int main() {
5 MyClass MyObj; //Оголосили об’єкт даного класу
6 return 0;
7 }

Роздiл атрибутiв призначений для оголошення змiнних класу, які


називаються членами даних. Їх типи в сукупностi задають множину можливих
47
значень, або станiв об'єктiв класу. Роздiл операцiй призначений для оголошення
і визначення дій, якi можна виконувати над об'єктами класу або, за
термінологією ООП, таких, що виконуються самими об'єктами. Такі операцiї
ще називаються функціями членами або методами класу. В сукупності вони
описують поведінку об'єктiв класу.

6.2.1 Класи та 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 мови. Змiна реалiзацiї при збереженнi
iнтерфейсу і семантики не впливає на програми, якi використовують даний
клас.
В С++ iнтерфейс класу оголошується в файлi заголовків (ФЗ) з
розширенням .hpp (.h), а реалiзацiя класу - в файлi з розширенням .cpp (.c). ФЗ
мiстить оголошення змiнних класу і заголовки (прототипи) функцiй, якi
реалiзовують операції класу.
Кожен член класу має додатковий статус, який задається оголошенням
його в одній з трьох допустимих мовою секцій. Ці секції визначаються
специфікаторами public, protected, private і задають права доступу до членів
класу.
Секція private (або приватна) визначає право доступу до членів,
оголошених в ній, лише для самого класу (тобто лише для функції-членів
класу). Члени, оголошені в цій секції, називаються приватними або закритими.
Секція protected (або захищена) визначає право доступу до членів як для самого
класу, так і для похідних від нього. Члени цієї секції називаються захищеними.
Секція public (або відкрита) ще більше розширює права, які надаються секцією
protected, додатковим введенням можливостей доступу до своїх членів для
об'єктів даного класу. Члени цієї секції називаються відкритими або
загальнодоступними.
1 class A{ // по замовчуванні приватна секція
2 int i1; // закритий по замовчуванні член даних
3 public: // оголошення відкритої секції
4 int i2; // відкритий член даних
5 private: // оголошення ще однієї приватної секції
6 int i3; // ще один закритий член даних

48
7 protected: // оголошення захищеної секції
8 int i4; // захищений член даних
9 public: // оголошення ще однієї відкритої секції
10 int i5; // ще один відкритий член даних
11 };

6.2.2Конструктори і деструктори
Конструктори і деструктори - це спецiальнi методи класу, якi
автоматично викликаються при створеннi або знищеннi об'єктiв.
Кожний клас повинен мати хоч би один конструктор, але, як правило, їх
задають декiлька. Цільове призначення конструкторів класу є двояким. З
одного боку (основного) - це створення "порожнього" об'єкта, тобто розподiл
пам'ятi для змiнних класу цього об'єкта. З іншого – це додаткова iнiцiалiзацiя
стану об'єкта, тобто заповненя "порожнього" об'єкта, оскільки саме в
конструкторi визначається, якими значеннями потрібно проiнiцiалiзувати
змiннi об'єкта.
Конструктори існують трьох типів: по замовчуванні, з параметрами і
конструктор копіювання (або конструктор копії). Кожен клас може містити
лише один конструктор по замовчуванні, один копіювання і довільну кількість
конструкторів з параметрами. Це визначає можливість перевантаження
конструкторів як звичайних функцій.
Наведемо приклади оголошення конструкторів всiх типiв для деякого
класу Patient:
1 class Patient {
2 char* m_s_Name; // закриті по замовчуванні
3 int m_n_Age; // члени даних
4 public:
5 // Конструктор по замовчуванню
6 Patient();
7 // Конструктори з параметрами для iнiцiалiзацiї
8 Patient(char* name, int Age);
9 Patient(char* name);
10 // Конструктор копiї
11 Patient(const Patient &source);
12 // iншi оголошення - можливi
13 };
14 //Тепер можна написати реалізацію цих конструкторiв:
15 // Конструктор по замовчуванню
16 Patient::Patient() {
17 m_s_Name = "";
18 m_n_Age = 0;
19 }
20 // Конструктори з параметрами
21 Patient::Patient(char* name, int Age) {
22 m_s_Name = name;
23 m_n_Age = Age;

49
24 }
25 // Конструктор перетворення типу
26 Patient::Patient(char* name) {
27 m_s_Name = name;
28 }
29 // Констуктор копiї
30 Patient::Patient(const Patient &source) {
31 m_s_Name = source.m_s_Name;
32 m_n_Age = source.m_n_Age;
33 }
34
35 //Тепер стають можливими оголошення
36 //об'єктiв, якi приводять до виклику
37 //вiдповiдних конструкторiв:
38 // Виклик конструктора по замовчуванню
39 Patient NN;
40 // Виклики конструкторів з iнiцiалiзацiєю
41 Patient Ivanov ("Ivanov",35), Petrov ("Petrov");
42 // Виклик конструктора копiї
43 Patient theSameIvanov ("Ivanov")=Ivanov;

Деструктор - це метод явного, або неявного знищення об'єкта. Наприклад,


при виходi з блоку всi локальнi об'єкти знищуються і для цього автоматично
викликається деструктор. Звiльняючи пам'ять, яка зайнята об'єктом, деструктор
знищує всi результати роботи конструктора. Тiло декструктора, як правило -
порожнє, оскiльки система сама звiльняє пам'ять. Але якщо конструктор явно
виділяє динамічну пам'ять для членів об'єкта, то в тiлi деструктора має бути
оператор, який звiльняє цю пам'ять перед знищенням самого об'єкта.На відміну
від конструкторів, клас може містити лише один деструктор і обов'язково без
параметрів. Iм'я десктруктора - це iм'я вiдповiдного класу з префiксом "~".
Наприклад, ~Patient() – деструктор класу Patient.
Хоча синтаксично конструктори і деструктори є функціями, проте вони
не можуть повертати значень оскільки їх цільовим призначенням є створення та
знищення об'єктів класу.

6.2.3 Доступ до компонентiв класу


Доступ до компонентiв класу можливий за допомогою операторiв
доступу "." (крапка) і "–>". Оператор "." використовується з об'єктами.
Наприклад, в наведенiй програмi, до елемента print() здiйснено доступ за
допомогою об'єкта V наступним чином:
1 #include <stdio>
2 #include "Ccomplex.h"
3 main() {
4 const Ccomplex j(0,1),R(5000,0),c(0.02,0),L(0.03,0);
5 const double pi = 3.1415926;

50
6 double f = 60, Om = 2.*pi*f;
7 Ccomplex i(12,0), Z, V, OM(Om, 0);
8 Ccomplex Temp,Temp2;
9 Temp = Add(R, Mult(Mult(OM,j), L)); //R + j * OM * L
10 Temp2=Div(1,Mult(Mult(Om,j),c));
11 Z=Add(Temp,Temp2);
12 V = Mult(Z, i);
13 V.print();
14 }

Оператор "–>" використовується з вказiвниками на класовi об'єкти:


1 Ccomplex *W = new Ccomplex;
2 W->print();

Тут оператор new створює новий об'єкт типу Ccomplex з вказiвниками W


на цей об'єкт.

Лише після створення змінної класу (екземпляру, об’єкту), що має тип


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

1 class line {
2 public:
3 int x1, y1, x2, y2;
4 line(int _x1, int _y1, int _x2, int _y2);
5 void show();
6 void move(int x,int y);
7 ~line();
8 };
9 //… … … … … … … … …
10 void main()
11 {
12 // створюється об'єкт s класу line
13 line s(12,43,33,43);
14 int localx, localy;
15 localx=s.x1; //доступ до елементу-даних x1
16 localy=s.y1; //доступ до елементу-даних y1
17 s.show(); //доступ до елемента-функції show();
18 }

Отже, доступ до членів класу здійснюється за допомогою оператора


“крапка”(.), наприклад – object.data. Цей оператор повідомляє про те, що
потрібно забезпечити доступ до елементу класу data, змінна якого являє собою
окремий його екземпляр – object. Зрозуміло, що виклик елемента-функції без
вказівки екземпляра класу також неможливий. Синтаксис виклику такої функції
нагадує суміш синтаксису доступу до елементів-даних та виклику звичайної
51
функції – object.funk(). Кожний екземпляр класу має свою множину даних та
функції-елементи працюють з окремим набором даних, що належить змінній.
Екземпляр, для якого викликається функція-елемент, є “поточним” та всі
посилання на елементи-дані мають відношення саме до цього екземпляру, якщо
не посилаються явно на інший екземпляр. Адреса екземпляру передається
функції як неявний прихований аргумент, що має назву this (цей, поточний).
Цей тип завжди є покажчиком на екземпляр відповідного класу, що, зокрема,
знаходить своє застосування при перевантаженні операцій. Кожного разу, коли
функція-елемент посилається на елемент поточного класу без явної вказівки
екземпляру, завжди вважається, що цей екземпляр this:
1 class demo {
2 int i;
3 public:
4 void load_i(int val) {
5 this->i=val;
6 }
7 void get_i()
8 {
9 return this->i;
10 }
11 };

6.2.4 Статичні члени класу


Члени класу, оголошені з модифікатором класу пам'яті static, носять назву
статичних членів класу. Вони є загальними для усіх об'єктів даного класу:
змінивши значення статичного члену класу в одному об'єкті, ми отримаємо
змінене значення в усіх інших об'єктах. Оголошення статичних членів-даних
класу в середині оголошення класу не буде одночасно описом змінних,
оскільки при цьому під ці дані пам'ять не виділятиметься. Це слід робити в
програмі окремо. Таким чином, усі об'єкти класу посилатимуться на одне й те ж
саме місце у пам'яті.
Функції-елементи класу також можуть бути оголошені статичними, але
оскільки вони не отримують прихований покажчик this, вони не можуть
звертатися до нестатичних членів класу. Крім того, статична функція не може
бути віртуальною. Звертання до статичних функцій та елементів можливе
навіть тоді, коли ще не створено жодного об'єкту класу, в якому
використовуються статичні дані. Якщо функція func() є статичною функцією
класу А, її можна викликати таким чином:
А::func();

52
6.3 Порядок виконання
Розробити програму згідно варіанту, детально прокоментувати код:
1. Побудувати систему класів для опису плоских геометричних фігур:
коло, квадрат, прямокутник. Передбачити методи для створення
об'єктів, переміщення на площини, зміни розмірів і обертання на
заданий кут.
2. Побудувати опис класу, що містить інформацію про поштову
адресу організації. Передбачити можливість роздільної зміни
складових частин адреси, створення і знищення об'єктів цього
класу.
3. Скласти опис класу для представлення комплексних чисел з
можливістю задання дійсної і уявної частин як числами типів
double, так і цілими числами. Забезпечити виконання операцій
додавання, віднімання і множення комплексних чисел.
4. Скласти опис класу для об'єктів - векторів, що задаються
координатами кінців у тривимірному просторі. Забезпечити
операції додавання і віднімання векторів з одержанням нового
вектора ( чи суми/різниці), обчислення скалярного добутку двох
векторів, довжини вектора, cos кута між векторами.
5. Скласти опис класу прямокутників зі сторонами, паралельними
осям координат. Передбачити можливість переміщення
прямокутників на площині, зміну розмірів, побудова найменшого
прямокутника, що містить два заданих прямокутники, і
прямокутника, що є загальною частиною (перетинанням) двох
прямокутників.
6. Скласти опис класу для визначення одномірних масивів цілих
чисел (векторів). Передбачити можливість звертання до окремого
елементу масиву з контролем виходу за межі індексів, можливість
задання довільних границь індексів при створенні об'єкта і
виконання операцій поелементного додавання і віднімання масивів
з однаковими межами індексів, множення і ділення всіх елементів
масиву на скаляр, друку (виводу на екран) елементів масиву по
індексах і всього масиву.
7. Скласти опис класу для визначення одномірних масивів рядків
фіксованої довжини. Передбачити можливість звертання до
окремих рядків масиву по індексах, контроль виходу за межі
індексів, виконання операцій поелементного зчеплення двох
масивів з утворенням нового масиву, злиття двох масивів з

53
виключенням повторюваних елементів, друк (вивід на екран)
елементів масиву і всього масиву.
8. Скласти опис класу многочленів від однієї змінної, що задаються
ступенем многочлена і масивом коефіцієнтів. Передбачити методи
для обчислення значення многочлена для заданого аргументу,
операції додавання, віднімання і множення многочленів з
одержанням нового об'єкта - многочлена, друк (вивід на екран)
опису многочлена.
9. Скласти опис класу одномірних масивів рядків, кожен рядок
задається довжиною і покажчиком на виділену для неї пам'ять.
Передбачити можливість звертання до окремих рядків масиву по
індексах, контроль виходу за межі індексів, виконання операцій
поелементного зчеплення двох масивів з утворенням нового
масиву, злиття двох масивів з виключенням повторюваних
елементів, друк (вивід на екран) елементів масиву і всього масиву.
10.Скласти опис об'єктного типу TMatr, що забезпечує розміщення
матриці довільного розміру з можливістю зміни числа рядків і
стовпців, вивід на екран підматриці будь-якого розміру і всієї
матриці.
11.Створіть клас для харчових продуктів, який включає назву, вагу
порції, енергетичну цінність (в калоріях), вміст білків, жирів та
вуглеводів. Напишіть функцію, яка згідно заданого переліку
продуктів обчислює сумарну енергетичну цінність обіду.
12.Реалізуйте клас person, який містить дані для зберігання ПІБ, віку,
професії, домашньої адреси та телефону людини. Напишіть
функцію person::print(), яка виводить на екран дані про особу у
вигляді візитної картки (відцентрувати ПІБ і т.п.)
13.Спроектуйте та реалізуйте клас quadratic для зберігання
квадратного многочлена. Напишіть методи для знаходження
дискримінанту, коренів многочлена та виводу многочлена на екран
у звичному математичному вигляді.
14.Створіть клас для зберігання цілих чисел довжиною 10 байт.
Забезпечте виконання основних арифметичних операцій над
об'єктами класу та стандартними цілими типами даних.
15.Для класу з варіанту 4 напишіть оператори вставки в потік (<<) та
виділення з потоку (>>). Створіть методи для перетворення
числового значення, що міститься в об'єкті, в стрічку та навпаки, із
стрічки в число.

54
16.Реалізуйте клас matrix для зберігання цілочисельних матриць
розміром до 10х10. Забезпечте індексацію елементів матриці, друк
заданого стовпця, заданої стрічки та матриці загалом.
17.Для класу з варіанту 6 створіть методи для знаходження
максимального та мінімального елементів матриці, а також метод
для множення матриць (перевантажений оператор *).
18.Створіть клас vector для зберігання цілочисельного одномірного
масиву розмірністю від 10 до 10 000 елементів. Пам'ять під
елементи масиву виділяйте динамічно. Забезпечте індексацію
елементів масиву.
19.Для класу з варіанту 8 реалізуйте методи для знаходження
мінімального та максимального елементу масиву, сортування
елементів у зростаючому порядку.
20.Розробіть клас myString для роботи із стрічковими даними. Клас
повинен містити методи для роботи з потоками (<< та >>).
Потрібно забезпечити можливість конкатенації стрічок (оператор
+), операції присвоєння (=) та знаходження довжини стрічки.
21.Створити клас «точка з її координатами та кольором» . На його базі
створити клас «лінія» (задавати двома точками) з функціями:
відображення на екрані та переміщення по екрану. Також функції,
які б повертали координати середини відрізка та довжину відрізка.
22.Створити клас книга в якому містилась би інформація про автора,
рік видання, видавництво, тему, об’єм (к-ті сторінок). Створити
методи як і б виводили список книжок одної тематики.
23.Створити клас книга в якому містилась би інформація про автора,
рік видання, видавництво, тему, об’єм (к-ть сторінок). Створити
методи як і б виводили всі книжки одного автора.
24.Створити клас книга в якому містилась би інформація про автора,
рік видання, видавництво, тему, обсяг (к-ть сторінок). Створити
методи як і б сортували бібліотеку за роками видання.
25.Створити базовий клас персона з даними про неї. Надбудовою має
бути клас студент з доповненими даними про місце навчання та
групу та клас група зі списком студентів. Передбачити функцію
сортування записів про студентів в об’єкті група.
26.Використовуючи класи задачі 26 (доповнити клас студент полем
хобі), створити функцію яка б з масиву студентів створювала їх
групу, відбір робити за вподобаннями.
27.Створити клас регіон з наступними даними: назва обл., к-ть
мешканців, площа, к-ть навчальних закладів, к-ть промислових

55
підприємств. Створити метод для виконання наступної дії: вивести
назви областей з найбільшою і найменшою густотою населення.
28.Створити клас регіон з наступними даними: назва обл., к-ть
мешканців, площа, к-ть навчальних закладів, к-ть промислових
підприємств. Створити метод для виконання наступної дії: вивести
назви областей з найбільшою і найменшою зайнятістю населення.
29.Створити клас регіон з наступними даними: назва обл., к-ть
мешканців, площа, к-ть навчальних закладів, к-ть промислових
підприємств. Створити метод для виконання наступної дії:
побудувати стовпчикову діаграму зайнятості населення всіх
областей.
30.Створити клас регіон з наступними даними: назва обл., к-ть
мешканців, площа, к-ть навчальних закладів, к-ть промислових
підприємств. Створити метод, який би малював на екрані коло
(співрозмірне з площею) поділене на 3 сектора кожен з яких іншим
кольором та має означати зайнятість населення, к-ть населення на
один навчальний заклад, густота населення.

6.4 Порядок захисту


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

6.5 Контрольні запитання


1. Поняття класу та об’єкту.
2. Що розуміють під об’єктно-орієнтованим аналізом?
3. Що розуміють під об’єктно-орієнтованим проектуванням?
4. Як визначається об’єкт у предметній області, у програмній реалізації?
Чи розрізняються поняття об’єкт, клас, екземпляр класу?
5. Які основні принципи ООП?
6. Що таке абстракція в контексті ООП?
7. Що таке інкапсуляції?
8. Що таке успадкування?
9. Що таке поліморфізм?
10.Що означає повторне використання коду в контексті ООП?
11.Які переваги ООП?

56
Лабораторна робота 7. Робота з класами. Реалізація принципу
наслідування.

Мета роботи: Ознайомлення з поняттям похiдного класу i вивчення


способiв його створення.

7.1 Ви навчитесь:
По завершенні цього розділу Ви будете вміти:
 створювати ієрархію класів
 коректно описувати конструктори та деструктори в класах
нащадках

7.2 Теоретичні відомості


Успадкування – це співвідношення між класами, коли один клас
використовує структурну або функціональну частину іншого (інших) класів.
Для початку розглянемо структуру звичайного класу, що має справу з
описом людей, які працюють на одній фірмі. Пропонується така структура:
1 class employee
2 { // тип - клас «службовець»
3 char *name; // ім’я
4 short age; // вік
5 short department; // відділ
6 int salary; // зарплата
7 employee *next; // покажчик на представника класу
8 }

Список однотипних службовців буде пов’язаний через поле next. Тепер


окремо визначимо клас manager:
1 class manager
2 {
3 employee emp; // запис про менеджера як службовця
4 employee *group; // підпорядковані службовці менеджера
5 short level ; // рівень та інші характеристики
6 }

Таким чином, дані, що відносяться до службовця employee, зберігаються


в члені emp класу manager. Все ніби очевидно, однак для компілятора немає
вказівки, що покажчик на менеджера manager* є покажчиком на службовця
employee* , виходячи з контексту структури. Більше того, зовсім немає нічого
такого, що виокремлює член класу manager emp, що є типом employee. Можна,
звичайно, написати спеціальний код, що застосовує до manager* явне
перетворення типу, або розмістити у списку службовців адресу члена emp – все
57
це заслуговує на увагу, але й на додаткові витрати. Проте коректний підхід тут
полягатиме саме у застосуванні механізму успадкування, аби встановити, що
менеджер є службовцем з деякою допоміжною інформацією, тобто встановити,
що один з класів (похідний) в якійсь мірі містить, повторює функціональну
частину іншого (базового) класу.
Синтаксис успадкування:
class Base{
// протокол базового класу
};
class Derived: [public/protected/private] Base
{
//протокол похідного класу
};

class employee // тип - клас «службовець»


{
// протокольна частина класу employee
};
class manager: employee
{
// протокольна частина класу manager
};

У нашому випадку клас manager є похідним класом від класу employee, а


клас employee є базовим класом для класу manager, що можна відобразити
наступною схемою (UML діаграмою):

Клас employee

Клас manager

Рис. 7.2.1. Схема відношення успідкування між класами


У такому випадку об’єкт похідного класу додатково до власного члена
group матиме члени класу employee (name, age и т.д.), що, в принципі,
відповідає логіці даної задачі. Маючи визначення описаних вище класів, можна
створити список службовців, деякі з яких є менеджерами, що наведено нижче.
1 void f()
2{
3 manager m1, m2;

58
4 employee e1, e2;
5 employee* elist;
6 elist = &m1; // розмістити m1, e1, m2 та e2 в elist
7 m1.next = &e1;
8 e1.next = &m2;
9 m2.next = &e2;
10 }

Звернемо увагу на таке: оскільки менеджер є службовцем, покажчик на


employee може посилатися не тільки на об’єкт свого класу, але й на похідний
об’єкт класу – manager. Однак службовець необов’язково є менеджером, тому
використовувати employee* замість manager* є неможливим.

7.2.1 Керування доступом при успадкуванні


Повернемося до синтаксису успадкування. Специфікатори доступу public,
private, protected при призначенні типу успадкування можуть пропускатися (як,
до речі, і було у нашому першому прикладі зі службовцями та менеджерами),
при цьому керуються наступними правилами:
– якщо визначається class, то по замовчуванню похідний клас
приймається як private;
– якщо доступ не вказаний в успадкуванні при описі struct, то по
замовчуванню він приймається як public;
Наступна таблиця містить визначення рівня доступу в середині похідного
класу. У першій колонці – специфікатор доступу, що визначає успадкування
між класами, у двох подальших – рівень доступу у базовому та похідному
класах:

Таблиця 7.2.1 Рівні доступу у базових та похідних класах при успадкуванні


Тип успадкування Доступ у Доступ у
class A: [ ]class В базовому класі А похідному класі В
public private недоступно
public public
protected protected
private private недоступно
public private
protected private
59
protected private недоступно
public protected
protected protected

Слід дотримуватися наступних правил успадкування методів у похідному


класі:
 Оскільки конструктори не успадковуються, похідні класи повинні
мати власні конструктори. Тут можуть бути дві ситуації:
o якщо у конструкторі похідного класу відсутній явний виклик
конструктора базового класу, автоматично викликається конструктор
базового класу по замовчуванню (той, що не має параметрів). Для
ієрархії декількох рівнів конструктори базових класів викликаються,
починаючи з найвищого рівня.
o якщо конструктор базового класу потребує вказівку параметрів, він
повинен бути явно викликаний в конструкторі похідного класу
списком ініціалізації [1].
 Оскільки деструктор не успадковуються та програмою не визначений
деструктор у похідному класі, його буде згенеровано по
замовчуванню і через нього викликано деструктори усіх базових
класів. У класовій ієрархії деструктори викликаються у порядку,
зворотному до виклику конструкторів; спочатку деструктор поточного
класу, а потім деструктор базового класу
 Похідний клас може перевизначати метод з одним і тим же ім’ям, що і
у базовому класі, відповідно коректуючи його поведінку для себе. Аби
запобігти неоднозначностям, рекомендовано перевизначати лише
віртуальні методи класів.

7.2.2 Множинне наслідування


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

60
class S: X, Y, Z {...};
клас S породжений класами X, Y, Z, звідки він успадковує компоненти.

7.3 Порядок виконання


Згідно з номером варіанта спроектувати класи, реалізувавши
конструктори та відповідні методи. В головній функції проілюструвати їх
використання. Побудувати UML діаграму класів.

1. Клас точок
Базовий клас (точки у двовимірній площині з цілочисельними
координатами):
Конструктори: за замовчуванням, з параметрами та копіювання.
Деструктор.
Функції: обчислення відстані між точками; додавання координат двох
точок; введення - виведення на екран; перевірка збіжності двох точок.
Похідний клас: пікселів на екрані (точки, які мають колір).

2. Клас комплексних чисел


Базовий клас (уявних чисел):
Конструктори: за замовчуванням, з параметрами та копіювання.
Деструктор.
Функції: додавання; віднімання; множення на дійсне число; виведення
інформації на екран.
Похідний клас: комплексних чисел.

3. Відомість успішності студентів (2 класи: базовий — студент; похідний


— студент з відомістю успішності)
Базовий клас (студент):
Змінні: ім’я, вік, вищий навчальний заклад.
Конструктори: за замовчуванням, з параметрами та копіювання.
Деструктор.
Функції: задання вищого навчального закладу; змінювання імені;
введення-виведення інформації про вік; виведення всіх даних.
Похідний клас: студент з відомістю успішності — до базового класу
додається масив оцінок.

4. Динамічний одновимірний масив цілих чисел


Базовий клас:
Конструктори: за замовчуванням, з параметрами та копіювання.
61
Деструктор.
Функції (дві-три на вибір): запис / одержання елемента масиву;
виведення масиву на екран; пошук елемента масиву; інформація про
максимальний та поточний розміри масиву; очищення масиву.
Похідний клас: динамічний одновимірний масив цілих чисел з
довільними (включаючи й від’ємні) межами.

5. Динамічний двовимірний масив цілих чисел (матриця)


Базовий клас:
Конструктори: за замовчуванням, копіювання, з різною кількістю
параметрів.
Деструктор.
Функції (дві-три на вибір): запис / одержання елемента масиву; виведення
масиву на екран; пошук елемента масиву; інформація про максимальний та
поточний розміри масиву; очищення масиву.
Похідний клас: динамічний двовимірний масив цілих чисел з довільними
(включаючи й від’ємні) межами.

6. Послідовні кільцеві структури даних (стеки, черги)


Базовий клас (кільцева структура даних):
Конструктори: за замовчуванням, з параметрами та копіювання.
Деструктор.
Функції: виведення всіх елементів на екран; інформація про максимальну
та поточну кількість елементів.
Похідний клас: стек.
Функції:
запис / одержання елемента;
знищення заданої кількості або всіх елементів.

7. Послідовні кільцеві структури даних (стеки, черги)


Базовий клас (кільцева структура даних):
Конструктори: за замовчуванням, з параметрами та копіювання.
Деструктор.
Функції: виведення всіх елементів на екран; інформація про максимальну
та поточну кількість елементів.
Похідний клас: черга.
Функції:
запис / одержання елемента;
знищення заданої кількості або всіх елементів.

62
8. Динамічний список (2 класи: елемент списку, список перебувають у
відношенні агрегації)
Конструктори: за замовчуванням, з параметрами та копіювання.
Деструктор.
Функції (дві-три на вибір): вставлення елемента з голови (хвоста) у
заданому місці; видалення елемента з голови (хвоста) із заданого місця;
виведення списку на екран; пошук елемента списку; інформація про кількість
елементів списку; очищення списку; одержання голови (хвоста) списку;
одержання наступного (попереднього) елемента.

9. Реалізація бінарного дерева (2 класи: вузол дерева, дерево перебувають


у відношенні агрегації)
Конструктори: за замовчуванням, з параметрами та копіювання.
Деструктор.
Функції (дві-три на вибір): включення вузла дерева у заданому місці;
знищення частини дерева із заданого місця; виведення дерева на екран;
пошук елемента по дереву; інформація про структуру дерева; очищення
дерева; обхід дерева (перебирання всіх елементів).

10. Граф (2 класи: вузол графу, граф перебувають у відношенні агрегації)


Конструктори: за замовчуванням, з параметрами та копіювання.
Деструктор.
Функції (дві-три на вибір): включення до графу елемента зі своїми
зв’язками; видалення із графу елемента зі своїми зв’язками; виведення графу на
екран; пошук елемента графу; інформація про структуру графу; очищення
графу; обхід графу (перебирання всіх елементів); отримання шляхів між двома
заданими вузлами.

11. Множина (2 класи: елемент множини, множина перебувають у


відношенні агрегації)
Конструктори: за замовчуванням, з параметрами та копіювання.
Деструктор.
Функції (дві-три на вибір): додавання елемента до множини; видалення
елемента із множини; виведення всіх елементів множини на екран; перевірка
входження елемента до множини; очищення множини; перебирання всіх
елементів множини.

12. Текст (2 класи: рядок, текст перебувають у відношенні агрегації)


Конструктори: за замовчуванням, з параметрами та копіювання.
Деструктор.
63
Функції (дві-три на вибір): вставляння (видалення) символу у даному
рядку, у даному місці; очищення заданого рядка; видалення заданого рядка;
вставляння рядка у задане місце; пошук рядка у тексті; очищення тексту.

7.4 Порядок захисту


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

7.5 Контрольні запитання


1. Що таке успадкування?
2. Опишіть структуру об’єкта похідного класу.
3. Опишіть правила доступу для різних типів успадкування.
4. Як відбувається конструювання об’єктів при множинному успадкуванні?

Лабораторна робота 8. Реалізація принципу поліморфізму в ООП.


Перевантаження операцій.

Мета роботи: засвоїти принципи перевантаження операцій,


навчитися створювати ієрархії класів та використовувати поліморфізм .

8.1 Ви навчитесь:
По завершенні цього розділу Ви будете вміти:
 користуватися перевантаженням функцій,
 реалізовувати перевантаження операцій
 реалізовувати механізм віртуальних функцій в С++.

8.2 Теоретичні відомості


8.2.1 Перевантаження функцій
Перевантаження функцій означає, що для передачі повідомлень об’єктам
різних класів можна скористатись функціями з однаковими іменами і, що
кожний об’єкт буде реагувати відповідним чином.
Під час виклику функції f процес пошуку потрібної із множини
перевантажених відбувається як пошук найбільшої відповідності типів
формальних і фактичних параметрів.
8.2.2 Перевантаження операцій.

64
На відміну від інших мов програмування С++ допускає перевантаження
операцій =, +, -, *, ==, && та інших для будь-яких типів даних. У результаті
компілятор визначає типи операндів, і запускається відповідний варіант
операції. Перевантажувати можна навіть операцію виклику функції.
В С++ допустимі перевантаження таких операцій та операторів:
+, -, /,*, %, ^, &, !, ~, =, <, >, +=, - =, * =, / =, % =, ^ =, & =, / =, <<, >>, ==, !
=, < =, > =, &&, //, ++, --, -> *, [], (), new, new[], delete, delete[]. Не можуть бути
переввантажені оператори: ::, ., .*, :, sizeof() та непередбачені в синтаксисі
мови. У перевантажених операторах зберігається пріоритет і порядок
виконання у виразах, закріплені за даними операторами.
Перевантажувати оператори можна двома способами:
1. Звичайний опис функції з назвою operator знак. Наприклад:
1 Point operator +(Point A, Point B)
2{
3 // тіло функції }

Тоді вираз A+B інтерпретується як operator +(A, B).


2. Опис у тілі класу методу з тією самою назвою. Тоді викликається
метод для першого операнда, і йому як аргументи передаються інші
операнди:
1 class Point
2 {
3 // тіло класу
4 Point operator +(Point p);
5 };

У цьому випадку вираз A+B інтерпретується як A.operator +(B).


Деякі операції — такі як =, new, delete, можна перевантажувати тільки
другим способом.

8.2.3 Дружні класи і дружні функції.


Оскільки деякі операторні функції можуть бути зовнішніми, виникає
проблема доступу до прихованих частин класу. В цьому випадку
використовують так звані дружні функції. Дружні функції повинні бути
оголошені в середині опису класу, з яким вони дружні, за допомогою префікса
friend. Наприклад:
1 class A{int q; . . . friend void func (A, int);. . .};
2 void func (A a1, int i) {a1. q =i;};

Якщо усі функції-члени одного класу (Х) є дружніми для другого класу
(Y), говорять, що клас Х – дружній класу Y. Тоді цей факт оголошують так:
1 class Y{. . . friend class X;. . . };

65
8.3 Порядок виконання
8.3.1 Перевантажити операції.
Використати спроектовані класи згідно з варіантом та спроектовані
об’єкти цих класів у лабораторній роботі 7.
1. Операції: = (присвоювання),+, – (поелементні математичні операції).
2. Операції: = (присвоювання),+, – (поелементні математичні операції).
3. Операції: = (присвоювання),== (перевірка на рівність масивів
оцінок).
4. Операції: [ ] (одержання елемента масиву), = (присвоювання
масивів),+, –, * (поелементні математичні операції).
5. Операції: = (присвоювання масивів),+, –, * (поелементні
математичні операції).
6. Операції: = (присвоювання).
7. Операції: = (присвоювання).
8. Операції: = (присвоювання).
9. Операції: = (присвоювання).
10. Операції: = (присвоювання).
11. Операції: = (присвоювання),+ (об’єднання множин), (перетин
множин), (різниця множин).
12. Операції: = (присвоювання)
+ (додавання одного тексту до іншого).

8.3.2 Ієрархія класів.


Спроектуйте ієрархію класів для представлення графічних об’єктів.
Головним базовим класом для усіх об'єктів є клас Point – точка на площині (у
просторі) з її координатами. Опис класів слід розмістити у заголовочному
файлі, а визначення функцій і головну функцію програми – в двох окремих
файлах. Передбачте методи для створення об’єкта, його переміщення на екрані,
зміни розмірів та кольору, обертання на заданий кут. Використайте захищення
даних для ізоляції елементів-даних класу від підпрограм, в яких цей клас
використовується, а також поліморфізм для визначення дії певних функцій у
класовій ієрархії. Напишіть головну функцію, що демонструє роботу з цим
класом. Програма повинна містити меню, що дозволяє здійснити перевірку всіх
методів класу
1. коло 9. відрізок у просторі
2. кільце 10.відрізок на площині
3. паралелепіпед у просторі 11.шестикутник
4. сфера 12.вектор у просторі
66
5. прямокутник 13.курсор на екран
6. вектор на площині 14.квадрат
7. багатокутник 15.конус
8. рівнобедрений трикутник 16.трапеція

8.4 Порядок захисту


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

8.5 Контрольні запитання


1. Що таке перевантаження функцій?
2. Наведіть приклади перевантаження унарних операторів.
3. Наведіть приклади перевантаження бінарних операторів.
4. Поясніть синтаксис перевантажених операцій потокового введення-
виведення.
5. Як забезпечити можливість явного і неявного перетворення типів?
6. У яких випадках використовують віртуальні функції?
7. Що таке дружні класи і дружні функції?

67
Лабораторна робота 9. Віртуальні функції . Шаблони класів

Мета роботи: засвоїти принципи роботи з віртуальними функціями,


раннім і пізнім зв’язуванням та шаблонами класів.
Поняття віртуальної функції. Пізнє зв’язування. Динамічний поліморфізм.
Абстрактні класи. Шаблони класів

9.1 Ви навчитесь:
По завершенні цього розділу Ви будете вміти:
 Описувати та використовувати віртуальні функції;
 Працювати із шаблонами класів.

9.2 Теоретичні відомості


9.2.1 Пізнє зв’язування.
Якщо у класах, зв’язаних відносинами успадкування, існують функції з
однаковими сигнатурами, це означає, що об’єктам цих класів можуть бути
передані однакові повідомлення. Може виникнути ситуація, коли на етапі
компіляції відомо, яке повідомлення потрібно передати, але тільки під час
виконання стане відомо об’єкту якого класу. У цьому випадку використовують
механізм пізнього зв’язування.
В С++ пізнє зв’язування реалізоване за допомогою функцій-членів, які
називаються віртуальними функціями.
Віртуальну функцію оголошують у базовому класі за допомогою
префікса virtual, а потім переозначають у похідних класах.
Віртуальні функції покладаються на додаткову структуру даних, яка
підтримує зв’язок між різними версіями функцій. Це таблиця віртуальних
функцій (virtual method table-vtbl) – таблиця вказівників на віртуальні функції,
яка конструюється для кожного класу окремо. Всі екземпляри класу містять
вказівник на цю таблицю.
Такий механізм дозволяє асоціювати і зв’язати повідомлення з методом
під час виконання програми автоматично. Програміст тільки визначає дії, які
повинен виконати об’єкт, отримавши повідомлення.
Щоб досягти пізнього зв’язування для об’єкта, необхідно скористатись
вказівником або посиланням на нього. Для відкритих похідних класів
вказівники і посилання на об’єкти цих класів сумісні з вказівниками і
посиланнями на об’єкти базового класу. Обрана функція-член залежить від
класу, на об’єкт якого вказана, а не від типу вказівника.
1 class Animal{ int age;
2 public: . . . virtual void Ask(); };

68
3 class Dog: public Animal{ char* breed;
4 public: . . . void Ask(); };
5 class Cat: public Animal{ char* color;
6 public: . . . void Ask(); };
7 void Animal:: Ask(){cout<<«I’m animal ! «;};
8 void Dog:: Ask(){cout<<«I’m “<<breed <<’!’;};
9 void Cat:: Ask(){cout<<«I’m “<<color<<« cat! «;};
10
void main()
11
{Animal *a[3];
12
Animal a; Cat c(“white»); Dog d(“Doberman»);
13
a[0] = &a; a[1] = &c; a[2] = &d;
14
for (int i; i=0; i<3) a[i]->Ask(); };
15
//Результат: I’m animal! I’m white cat! I’m Doberman!

Якщо в класі присутня хоча б одна віртуальна функція, його деструктор


потрібно визначити як віртуальний [1].
9.2.2 Шаблони
Визначаючи параметризований клас, ми створюємо його каркас (шаблон),
що описує усі алгоритми, які використовуються класом. Фактичний тип даних,
над яким проводитимуться маніпуляції, буде вказаний в якості параметру при
конкретизації об’єктів цього класу. Компілятор автоматично згенерує
відповідний об’єкт на основі вказаного типу. Загальна форма декларування
параметризованого класу буде такою:
template <class Type> class class_name
{
// протокольна частина класу
}

Визначення тіла класу аналогічно звичайному визначенню плюс


використанню списку аргументів шаблону. Тип Type являє собою ім’я типу
шаблону, яке в кожному випадку реалізації буде замінюватися конкретним
типом даних. Типи можуть бути як стандартні, так і визначені користувачем,
для їх опису завжди використовується ключове слово class. При необхідності
можливо визначити більше одного параметризованого типу даних,
використовуючи їх список через кому. У межах визначення класу шаблонне
ім’я можна використовувати у будь-якому місці. Для створення конкретної
реалізації використовується наступна форма:
class_name <type> ob;

До речі, елементи-функції, над якими оперуватиме клас, автоматично


стають параметризованими, тобто їх необов’язково декларувати за допомогою
ключового слова template.

69
При більш широкому розгляді шаблон класу – узагальнене визначення
сімейства класів, яке може використовувати не лише довільні типи, а й
константи. Синтаксис його узагальненого опису наступний:
template <список_аргументів_шаблону> class ім’я_класу
{
// визначення класу
}

Аргумент (список_аргументів_шаблону) може складатися :


 з ключового слова class , за яким слідує ідентифікатор, який
визначає параметризований тип (типовий параметр);
 з конкретного імені типу, за яким слідує ідентифікатор (нетиповий
параметр, константа);
Створивши представника шаблонного класу, надалі можливо працювати з
ним так само, як з представником звичайного класу.

Шаблон може мати кілька параметрів, які можуть бути: класами,


стандартними типами, шаблонами; аргумент шаблону може бути константним
виразом, адресою об’єкта чи функції; не може бути рядковим літералом.
1 template<class T> class Vector // шаблон
2{
3 T* v;
4 int size;
5 public:
6 Vector();
7 Vector(int);
8 //...
9 };
10 //Наведемо приклад створення об’єкта
11 // параметризованого класу:
12 int main()
13 { //...
14 Vector<int> vi; //інстанціювання
15 Vector<char*> vpc;
16 Vector<double> vd;
17 //...
18 }

Шаблони можна ефективно використовувати для успадкування.


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

70
Можна створювати шаблони класів, що походять як від класу, що не є
шаблоном, так і від шаблону класу. Класи чи шаблони класів можуть мати
члени-шаблони. Члени-шаблони не можуть бути віртуальними.

9.2.3 Організація стандартної бібліотеки. STL (Standard Template


Library).
Організація стандартної бібліотеки. Стандартна бібліотека визначена в
просторі імен std і кожний засіб стандартної бібліотеки стає доступним через
відповідний стандартний заголовковий файл, наприклад: # include <iostream>

Щоб усі імена із std оголосити глобальними потрібно скористатись using-


оголошенням:
using namespaсe std;

До складу стандартної бібліотеки входять такі основні засоби:


 контейнери (<bitset>, <set>, <map>, <stack>, <vector>, <list>,
<deque>, <queue>. . .);
 ітератори (<iterator>. . .);
 алгоритми (<algorithm>, <cstdlib>,<numeric>. . . );
 основні утiліти (<utility>, <memory>, <functional>, <ctime>);
 діагностика (<stdexcept>, <cassert>, <cerino>. . .);
 рядки (<string>, <stdlib>,. . .);
 уведення-виведення (<iostream>, <ios>, <istream>, <ostream>);
 локалізація (<local>, . . .);
 числа(<complex>, <valarray>, . . .).

Підхід, прийнятий в стандартній бібліотеці С++, базується на таких


поняттях, як послідовність, ітератор і алгоритм. Контейнер розглядається як
послідовність елементів, до кожного з яких можна звертатись за допомогою
ітератора [2].

9.3 Порядок виконання


Спроектувати шаблон для класу, створеного у лабораторній роботі 7,
згідно зі своїм варіантом. В основній програмі створити відповідні структури
простих (наприклад, список чисел або рядків) і складних даних (наприклад,
список об’єктів іншого класу) і продемонструвати роботу з ними.

71
9.4 Порядок захисту
Студент, який виконав завдання лабораторної роботи, подає письмовий
звіт про виконання лабораторної роботи (згідно інструкцій та вимог на сторінці
дистанційного курсу) і доповідає про результати та дає відповіді на запитання.
Виконане завдання оцінюється згідно системи контролю знань, умінь, навичок,
наведеної на відповідній сторінці дистанційного курсу.

9.5 Контрольні запитання


1. Пояснити призначення, синтаксис і особливості використання
шаблонів класів та функцій.
2. Пояснити загальний підхід до побудови і використання стандартного
контейнера STL.
3. Пояснити принципи побудови і використання основних контейнерів,
ітераторів і алгоритмів STL.

72
Використана література
1. Страуструп Б. Язык программирования С++ [Текст] / Бьерн Страуструп. 3-е
изд. — М. : БИНОМ, 2004. — 1104 с.
2. Х. Дейтел, П. Дейтел. Как программировать на С++. М.:Бином. 1998Р.
Лафоре. Обьектно–ориентированное программирование в С++. – СПб:
Питер, 2003 – 928 с.
3. Навч.-методичний посібник / В.В.Войтенко, А.В.Морозов. – Житомир:
ЖДТУ, 2004. – 324 стор.
4. Грейди Буч. Язык UML. Руководство пользователя, The UnifiedModeling
Language user guide / Буч Грейди, Рамбо Джеймс, Айвар Джекобсон. – Изд.
2-ое. – М.-СПб. : Изд-во "ДМК Пресс", Питер, 2004. – 432 с.
5. Дудзяний І. М. Об’єктно-орієнтоване моделювання програмних систем:
Навчальний посібник. – Львів: Видавничий центр ЛНУ імені Івана Франка,
2007. – 108 с.
6. Навч.-методичний посібник / В.В.Войтенко, А.В.Морозов. – Житомир:
ЖДТУ, 2004. – 324 стор.
7. Страуструп Б. Язык программирования С++. Специальное издание. —
Бином, 2008. — 1104 с.
8. Об’єктно-орієнтоване програмування: Методичні вказівки до
комп’ютерного практикуму для студентів напрямів підготовки 6.040303
«Системний аналіз», 6.040302 «Інформатика», 6.050101 «Комп’ютерні
науки» / Уклад.: І.В. Назарчук. – К. НТУУ “КПІ”, 2011. – 72 с.

73
Додаткова література
1. Ковалюк Т.В. Основи програмування. - К.: Видавнича група BHV, 2005.
2. Львов М.С., Співаковський О.В. Основи алгоритмізації та програмування.
Навч. посібник. - Херсон: Айлант. 2000. -214 с.
3. Применение UML 2.0 и шаблонов проектирования / Ларман Крэг — [3-е
изд.] ; пер. с англ. – М. : ООО «Издательский дом Вильямс», 2007. — 736 с.
4. Подбельский В.В. Язык Си++; Учеб.пособие.- М: Финансы и статистика,
2005.-500 с.
5. Климов А.М. С++. Практическое программирование . Решение типових
задач. – СПб:ВHV,2000.- 593с.
6. Павловская Т.А., Щупак Ю.А. С++. Объектно-ориентированное
программирование: Практикум. – СПб.: Питер,2004 -288 с.
7. Либерти Д. Освой самостоятельно C++ за 21 день. –М.:Вильямс, 2000. –
806с.
8. Седжвик Р. Фундаментальне алгоритмы на С++. Анализ/Структуры
данных/Сортировка/Поиск. – СПб:ВHV,2000.-608с.

74

You might also like