Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
+ООП_Навч_посібник.doc
Скачиваний:
7
Добавлен:
01.07.2025
Размер:
6.58 Mб
Скачать

12.5. Об'єднання і класи – споріднені типи

Той факт, що структури і класи – споріднені, зазвичай нікого не дивує; проте Ви можете здивуватися, дізнавшись, що об'єднання також пов'язані з класами "близькими відносинами". Згідно з визначенням мови програмування C++, об'єднання – це, по суті, аналогічний клас, у якому всі члени даних зберігаються в одній і тій самій області1. Об'єднання може містити конструктор і деструктор, а також функції-члени. Звичайно ж, члени об'єднання за замовчуванням відкриті (public), а не закриті (private).

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

Код програми 12.9. Демонстрація створення класу на основі об'єднання

#include <vcl>

#include <iostream> // Для потокового введення-виведення

#include <conio> // Для консольного режиму роботи

using namespace std; // Використання стандартного простору імен

union demoUnion { // Оголошення типу об'єднання

demoUnion(short int a); // Відкриті члени за замовчуванням

void showChars();

short int izm;

char ch[2];

};

// Оголошення параметризованого конструктора

demoUnion::demoUnion(short int a)

{

izm = a;

}

// Відображення символів, які становлять значення типу short int.

void demoUnion::showChars()

{

cout << ch[0] << " ";

cout << ch[1] << "\n";

}

int main()

{

demoUnion U_ob(1000); // Створення об'єкта об'єднання та надання

// йому числового значення

U_ob.showChars();

getch(); return 0;

}

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

12.6. Вбудовувані функції

Перед тим, як ми продовжимо засвоєння класу, дамо невелике, але важливе пояснення. Воно не належить конкретно до об'єктно-орієнтованого програмування, але є дуже корисним засобом мови програмування C++, який достатньо часто використовують у визначеннях класів. Йдеться про вбудовувану функцію (inline function), або функцію, що підставляється. Вбудовуваною називається функція, програмний код якої підставляється в те місце рядка програми, з якого вона викликається, тобто виклик такої функції замінюється її кодом. Існує два способи створення вбудовуваної функції. Перший полягає у використанні модифікатора inline. Наприклад, щоби створити вбудовувану функцію fun_f, яка повертає int-значення і не приймає жодного параметра, достатньо оголосити її таким чином.

inline int fun_f()

{

//...

}

Модифікатор inline повинен передувати всій решті аспектів оголошення функції.

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

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

Продемонструємо використання вбудовуваної функції на прикладі такої програми.

Код програми 12.10. Демонстрація механізму використання вбудовуваної функції

#include <vcl>

#include <iostream> // Для потокового введення-виведення

#include <conio> // Для консольного режиму роботи

using namespace std; // Використання стандартного простору імен

class buildClass { // Оголошення класового типу

int izm; // Закритий член за замовчуванням

public:

int getIzm();

void putIzm(int jzm);

};

inline int buildClass::getIzm()

{

return izm;

}

inline void buildClass::putIzm(int jzm)

{

izm = jzm;

}

int main()

{

buildClass S_ob; // Створення об'єкта класу

S_ob.putIzm(10);

cout << "izm= " << S_ob.getIzm() << "\n";

getch(); return 0;

}

У цій програмі замість виклику функцій getIzm() і putIzm() підставляють їх код. Так, у функції main() рядок

S_ob.putIzm(10);

функціонально еквівалентний такій настанові присвоєння:

S_ob.izm = 10;

Оскільки змінна izm за замовчуванням закрита у межах класу buildClass, то цей рядок не може реально існувати в коді функції main(), але за рахунок вбудовування функції putIzm() ми досягли того ж результату, одночасно позбавившись витрат системних ресурсів, взаємопов'язаних з викликом функції.

Важливо розуміти, що насправді використання модифікатора inline є запитом, а не командою, за якою компілятор згенерує вбудовуваний (inline-) код. Існують різні ситуації, які можуть не дати змоги компіляторові задовольнити наш запит. Ось декілька прикладів:

  • деякі компілятори не генерують вбудовуваного коду, якщо відповідна функція містить цикл, конструкцію switch або настанову goto;

  • найчастіше вбудовуваними не можуть бути рекурсивні функції;

  • як правило, вбудовування "не проходить" для функцій, які містять статичні (static) змінні.

Необхідно пам'ятати! Обмеження на використання вбудовуваних функцій залежать від конкретної реалізації системи, тому, щоб дізнатися, які обмеження є у Вашому випадку, зверніться до документації, що додається до Вашого компілятора.

Використання вбудовуваних функцій у визначенні класу

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

Код програми 12.11. Демонстрація механізму використання вбудовуваних функцій у визначенні класу

#include <vcl>

#include <iostream> // Для потокового введення-виведення

#include <conio> // Для консольного режиму роботи

using namespace std; // Використання стандартного простору імен

class buildClass { // Оголошення класового типу

int izm; // Закритий член за замовчуванням

public:

// Автоматично вбудовувані функції

int getIzm() { return izm;}

void putIzm(int jzm) { izm = jzm;}

};

int main()

{

buildClass S_ob; // Створення об'єкта класу

S_ob.putIzm(10);

cout << "izm= " << S_ob.getIzm() << "\n";

getch(); return 0;

}

У цій програмі функції getIzm() і putIzm() визначені в тілі оголошення класу buildClass і автоматично є вбудовуваними.

Звернемо Вашу увагу на те, як виглядають коди функцій, визначених "усередині" класу buildClass. Для дуже невеликих за обсягом функцій таке представлення коду програми відображає звичайний стиль мови програмування C++. Проте ці функції можна сформатувати так:

// Альтернативний запис вбудовуваних функцій у визначенні класу

class buildClass { // Оголошення класового типу

int izm; // Закритий член за замовчуванням

public:

// Вбудовувані функції

int getIzm()

{

return izm;

}

void putIzm(int jzm)

{

izm = jzm;

}

};

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

Варто знати! Визначення невеликих функцій-членів класу в оголошенні класу – звичайна практика в С++-програмуванні. Тут справа навіть не в засобі автоматичного вбудовування, а просто в зручності запису коду функції. Навряд чи Вам трапиться в професійних програмах, щоб короткі функції-члени визначалися поза їх класом.