Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Posibnyk_C_sum.doc
Скачиваний:
9
Добавлен:
29.08.2019
Размер:
1.63 Mб
Скачать

13 Класи

13.1 Приклад програмування класу

З розвитком засобів обчислювальної техніки появлялися й нові методики програмування, зокрема такі:

  • програмування безпосередньо в машинних кодах. Це найбільш трудомісткий вид програмування, який вимагав від програміста знання будови обчислювальної машини та особливостей машинних команд. Такі програми найважче налагоджувати, бо їхній текст містить усього два символи: 0 і 1;

  • програмування мовою асемблер. Робота програміста стала продуктивнішою, команди замінювалися більш зрозумілими словами, застосовувалися ідентифікатори змінних, автоматично розподілялася пам’ять комп’ютера;

  • програмування мовами високого рівня, таких, наприклад, як Фортран;

  • програмування мовами структурного програмування (Паскаль, С). Особливістю цієї методики є можливість застосування структур (іноді їх називають записами), вже розглянених нами в попередніх розділах;

  • об’єктно-орієнтоване програмування (С++).

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

ООП дозволяє змінити саму сутність процесу програмування. Матеріальний світ складається з предметів та явищ, кожний з яких має свої властивості і працює за певними алгоритмами. На сьогодні вже маємо величезну кількість прикладних програм, які їх моделюють (імітують). Якщо й надалі піти цим шляхом, то можна запрограмувати все на світі, тобто представити ці явища у вигляді певних об’єктів. Тоді робота програміста буде полягати лише в умінні відшукати потрібну програму (об’єкт) і пристосувати до конкретних потреб.

Поняття об’єкта тісно пов’язано з поняттям класу. Клас – це тип, він являє собою подальший розвиток поняття структури (мовою С – struct), головною його особливістю є наявність функцій. Об’єкт – це представник певного класу. Візьмемо, наприклад, клас “собака”, який моделює поведінку (бігає, подає голос) та властивості (колір, вага), загальні для всіх собак. Якщо такий клас доповнити відомостями про конкретного собаку (певну реакцію на подразники, білий колір, вага 10 кг), то одержимо об’єкт класу “собака”. Як видно з цього прикладу, класом можна назвати модель деякого абстрактного об’єкта.

Оголошення класу має такий вигляд:

class ім’я класу

{перелік закритих функцій і змінних;

public: перелік відкритих функцій і змінних;

}список об’єктів; //не обов’язковий

Дані, доступні для використання лише всередині об’єкта (закриті) оголошуються як private (прийнято за замовчуванням), а дані доступні ззовні – public. Закриті функції і змінні доступні тільки для інших членів всередині класу. Відкриті функції і змінні доступні для будь-якої частини програми, яка використовує даний клас. Функції, оголошені всередині опису класу, називаються функціями-членами. Їх визначення має такий вигляд:

тип ім'я класу:: ім'я функції-члена (параметри)

{ тіло функції;

}

Дві двокрапки після імені класу називаються операцією розширення області видимості.

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

Наведемо приклад. Оскільки, як уже вище було сказано, клас є розвитком поняття структури, використаємо відому з прикладу програми 7.2.2 структуру, додавши до неї функцію dd, яка збільшить у b разів денну зарплату k=456 Петренка П.П.

Програма, яка демонструє клас, подана в прикладі 13.1. Оскільки Петренко П.П. працює помічником бурового майстра, то названо цей клас pombura. Змінна k має тип int, який залишимо без зміни, бо зарплату копійками не видають. Нехай ця змінна, а зодно й масив s[25], будуть доступними лише членам класу, тому оголосимо їх як private (за замовчуванням). Функцію dd() оголошено як public, вона буде доступною поза класом. Їй передано параметр b – коефіцієнт збільшення денної зарплатні, який нехай дорівнює 1.5, це зроблено в головній програмі під час звенення до функції.

Окрім визначених програмістом функцій таких, наприклад, як dd(), клас мовою С++ при необхідності може мати ще такі дві: конструктор і деструктор. Від інших функцій вони відрізняються тим, що мають ім’я класу та автоматично запускаються на виконання, конструктор – під час оголошення об’єкта, а деструктор – при закінченні головної програми. Їх, зокрема, можна використати, першу – для ініціалізації змінних, а другу – для вилучення об’єктів з пам’яті. Ім’я деструктора відрізняється від імені конструктора тим, що починається з символа ~ (тільда). Подібно до звичайних функцій вони можуть приймати параметри, але не можуть повертати ніяких значень. Зауважимо, що клас може й не мати ні конструктора, ні деструктора, ні інших функцій.

Приклад 13.1 – Демонстрація класу

# include <stdio.h>

# include <string.h>

char master[25]="Петренко П.П.";

class pombura // Оголошення класу

{

char s[25];

int k;

public:

int dd (float);

pombura();

~pombura();

};

int pombura :: dd(float b) // Визначення функції dd( )

{

printf("Зарплата %d збільшується у %3.1f разів\n", k, b);

return k*b;

}

pombura :: pombura() // Визначення конструктора

{

strcpy(s, master);

k=456;

printf("Помбура %s мав зарплату %d\n", s, k);

}

pombura :: ~pombura() // Визначення деструктора

{

puts("Закінчення роботи");

}

int main(void) // Головна функція

{

pombura zarplata; // Оголошення об’єкта типу pombura

// pombura *p;

printf("Нова зарплата: %d\n", zarplata.dd(1.5));

// p=&zarplata;

// printf("Нова зарплата: %d\n", p->dd(1.5));

return 0;

}

Помбура Петренко П.П. мав зарплату 456

Зарплата 456 збільшується у 1.5 разів

Нова зарплата: 684

Закінчення роботи

У програмі прикладу 13.1 за допомогою конструктора проініціалізовано змінну k та масив s[]. А його запуск відбувається автоматично під час оголошення об’єкта zarplata.

На початку головної програми main() оголошено об’єкт zarplata типу pombura. Далі відбувається звернення до функції dd() з параметром 1.5, звернемо увагу на те, що в цьому зверненні вказано ім’я об’єкта zarplata, яке відділяється від імені функції символом крапка. Однак, при зверненні до неї в середині конструктора (тобто всередині класу) не вживається ні ім’я об’єкта, ні крапка.

Наприкінці прикладу 13.1 показано результати виконання програми в середовищі компілятора g++. Аналізуючи їх, можна прослідкувати послідовність роботи всіх чотирьох функцій.

Доступ до члена об’єкта можливий не тільки через точку, але й через вказівник на об’єкт подібно до прикладу 7.2.2, де відбувалося звенення до елементів структури. Доповнивши головну програму прикладу 13.1 оголошенням вказівника pombura *p та присвоївши йому значення адреси об’єкта p=&zarplata, можна так звернутися до функції dd(): p->dd(1.5). Цей варіант у прикладі показаний закоментареним.

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

13.2 – Особливості класу

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

Утворення похідного класу на основі взятого з прикладу 13.1 класу pombura і використаного як базового показано в прикладі 13.2. Наш Петренко П.П. працює позмінно, тому назвемо похідний клас zmina. Оскільки вся бригада перевиконала план і їм була призначена премія у 40 грошових одиниць, то нехай функція premia() цього класу її додасть.

Приклад 13.2 – Демонстрація похідного класу

# include <stdio.h>

# include <string.h>

char master[25]="Петренко П.П.";

class pombura // Базовий клас

{

char s[25];

int k;

public:

int dd (float);

pombura();

~pombura();

};

class zmina : public pombura // Похідний клас

{

public:

int premia(int);

};

int pombura :: dd(float b) // Функція базового класу

{

printf(" Зарплата %d збільшується у %3.1f разів \n", k, b);

return b*k;

};

pombura :: pombura() // Конструктор базового класу

{

strcpy(s, master);

k=456;

printf(" Помбура %s мав зарплату %d\n", s, k);

};

pombura::~pombura() // Деструктор базового класу

{

puts(" Закінчення роботи");

};

int zmina::premia(int dodatok) // Функція похідного класу

{

printf(" До зарплати буде додано: %d\n", dodatok);

return dd(1.5)+dodatok;

};

int main()

{

zmina new_zp; // Об’єкт типу похідного класу

printf(" Повна зарплата: %d\n", new_zp.premia(40));

return 0;

}

Помбура Петренко П.П. мав зарплату 456

До зарплати буде додано: 40

Зарплата 456 збільшується у 1.5 разів

Повна зарплата: 724

Закінчення роботи

У визначенні похідного класу zmina після його імені стоїть двокрапка, за якою знаходиться ключове слово public та ім’я базового класу pombura. Ключове слово public інформує компілятор про те, що, оскільки pombura буде успадковуватися, то всі його відкриті елементи будуть доступними елементам похідного класу. Проте всі закриті елементи базового класу залишаються закритими. У нашому випадку відкриту функцію dd() базового класу pombura викликає функція premia() похідного класу zmina з параметром 1.5.

Поліморфізм дозволяє одне й те ж ім’я функції використовувати в різних: базовому та похідному класах. У прикладі 13.3 використовуються два класи: базовий based і похідний poxid. Обидва вони містять по одній (разом дві) функції з одним і тим же іменем fun(), які, однак, мають видавати різні повідомлення.

Приклад 13.3 – Віртуальні функції

#include <stdio.h>

class based // Базовий клас

{

public : virtual void fun();

};

class poxid : public based // Похідний клас

{

public : void fun();

};

void based :: fun()

{

puts("Функція базового класу");

return;

};

void poxid :: fun()

{

puts("Функція похідного класу");

return;

};

int main()

{

based bob; //створення об’єкта базового класу

poxid pob; //створення об’єкта похідного класу

bob.fun(); //виклик функції базового класу

pob.fun(); //виклик функції похідного класу

return 0;

}

Функція базового класу

Функція похідного класу

Як видно з результатів, в обох випадках працювали різні функції, незважаючи на однакові їхні імена. Це стало можливим тому, що в оголошенні базового класу функцію зазначено як віртуальну, тобто маємо: virtual void fun(void). Тоді адреса функції визначається в процесі виконання програми. Цей процес називається “пізнім зв’язуванням” або “динамічним зв’язуванням”. Якби це оголошення не надавало функції віртуальних властивостей, тобто мало вигляд: void fun(void), то на стадії компілювання у всіх тих випадках, де зустрічається ім’я fun(), йому б призначалася одна й та ж адреса, причому вважалося б, що функція належить до базового класу. Такий процес установки адрес називається “раннім зв’язуванням” або “статичним зв’язуванням”.

Слід зауважити, що деякі компілятори визначають функцію віртуальною за замовчуванням.

13.3 Перевантаження функцій

Дві або більше функцій, які мають одне й те ж ім’я, називаються перевантаженими. Це стосується як функцій – членів класу, так самостійних, поза класом. Зазвичайно такі функції відрізняються кількістю і типом аргументів, а під час звернення до них компілятор мовою С++ це використовує та автоматично вибирає потрібну одну.

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

  1. Чим відрізняється клас від тега структури?

  2. Що таке відкриті та закриті члени класу?

  3. Що таке конструктор та деструктор? У якій послідовності і як вони запускаються на виконання?

  4. Який тип даних повертає конструктор?

  5. Чи може конструктор приймати вхідні параметри і, якщо може, то скільки і яких типів? Чи є тут якісь обмеження?

  6. Як утворюється об’єкт як екземпляр класу?

  7. Скільки класів та об’єктів може мати одна програма?

  8. Як можна звернутися до функції як члена класу? Чи можна це зробити за допомогою вказівника?

  9. Скільки похідних класів може мати один базовий?

  10. Поясніть роботу механізму спадкування.

  11. Як працюють віртуальні та перевантажені функції? Наведіть приклад, де було б доцільно їх використовувати. Чи можна функцію printf() вважати перевантаженою?

ПЕРЕЛІК РЕКОМЕНДОВАНИХ ДЖЕРЕЛ

  1. Горбійчук М.І., Семенцов Г.Н. Оптимізація процесу буріння глибоких свердловин. – Івано-Франківськ: Факел, 2003.

  2. Довгаль С.И., Сбитнев А.И. Интерфейс современной программной системы. – К.: Информсистема-сервис, 1994.

  3. Клим Б.В. Практикум з програмування мовою Сі. – Івано-Франківськ, Факел, 1989.

  4. Кочан, Стефан. Программирование на языке С, 3-е издание. : Пер. с англ.–М.: ООО “И.Д.Вильямс”, 2007

  5. Кочкодан Я.М. Технологія буріння нафтових і газових свердловин. – Івано-Франківськ, Факел, 1999.

  6. Мислюк М.А., Зарубін М.О. Моделювання явищ і процесів у нафтогазопромисловій справі: Навчальний підручник. – Івано-Франківськ: Екор, 1999.

  7. Прата С. Язык программирования С. Лекции и упражнения, 5-е издание.: Пер. с англ. – М.: Издательский дом “Вильямс”, 2006.

  8. Проценко В.С. i iн. Технiка програмування мовою Сi. – К.: Либiдь, 1993.

  9. Середюк М.Д., Якимів Й.В., Лісафін В.П. Трубопровідний транспорт нафти і нафтопродуктів: Підручник. – Івано-Франківськ, 2001.

  10. Стариков Ю.А. Мобильность программ и особенности реализаций языка Си. -М.: МП Память, 1992.

  11. Трой Д. Программирование на языке Си для персонального компютера IBM PC. – М.: Радио и связь, 1991.

  12. Хэзфилд Р., Кирби Л. и др. Искусство программирования на С. Фундаментальные алгоритмы, структуры данных и примеры приложений. Энциклопедия программиста: Пер. с англ./ Ричард Хэзфилд, Лоуренс Кирби и др. – К.: Издательство “ДиаСофт”, 2001.

  13. Шилдт, Герберт. Полный справочник по С, 4-е издание. : Пер. с англ. – М. : Издательский дом “Вильямс”, 2010

  14. Юрчишин В.М., Клим Б.В., Горбаль М.Б. Програмування мовою С. – Навчальний посібник. – Івано-Франківськ: ІФНТУНГ, 2009

g++ -Wall ./pos_13_1++.c -o pos_13_1++

./pos_13_1++;

182

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]