Урок №64. Структури

  Юрій  | 

  Оновл. 17 Чер 2020  | 

 111

У програмуванні є багато випадків, коли може знадобитися більше однієї змінної для представлення певного об’єкта.

Навіщо потрібні структури?

Наприклад, для представлення самого себе, ви, швидше за все, захочете вказати своє ім’я, день народження, зріст, вагу, тощо:

Тепер у вас є 6 окремих незалежних змінних. Якщо ви захочете передати інформацію про себе в функцію, то вам доведеться передавати кожну змінну окремо. Крім того, якщо ви захочете зберігати інформацію про когось ще, то вам доведеться додатково оголосити ще 6 змінних на кожну людину! Неозброєним оком видно, що така реалізація не дуже ефективна.

На щастя, C++ дозволяє програмістам створювати свої власні користувацькі типи даних — типи, які групують декілька окремих змінних разом. Одним з найпростіших користувацьких типів даних є структура. Структура дозволяє згрупувати змінні різних типів даних в єдине ціле.

Оголошення і визначення структур

Оскільки структури визначаються програмістом, то спочатку ми повинні повідомити компілятору, як структура взагалі буде виглядати. Для цього використовується ключове слово struct:

Ми визначили структуру з ім’ям Employee. Вона містить 3 змінні:

   id типу short;

   age типу int;

   salary типу double.

Ці змінні, які є частиною структури, називаються членами структури (або ще “полями структури”). Employee — це просте оголошення структури. Хоч ми і вказали компілятору, що вона має змінні-члени, пам’ять під неї зараз не виділяється. Імена структур прийнято писати з великої літери, щоб відрізняти їх від імен змінних.

Попередження: Однією з найпростіших помилок в C++ є забути вказати крапку з комою в кінці оголошення структури. Це призведе до помилки компіляції в наступному рядку коду. Сучасні компілятори, такі як Visual Studio 2010 і вище, вкажуть вам, що ви забули крапку з комою в кінці, але старіші компілятори можуть цього і не зробити, через що таку помилку буде важко знайти. Про те, як встановити Visual Studio або яку вибрати IDE ми вже говорили в уроці №4.

Щоб використовувати структуру Employee, нам потрібно просто оголосити змінну типу Employee:

Тут ми визначили змінну типу Employee з ім’ям john. Як і у випадку зі звичайними змінними, визначення змінної структури призведе до виділення для неї пам’яті.

Оголосити можна і декілька змінних однієї структури:

Доступ до членів структур

Коли ми оголошуємо змінну структури, наприклад, Employee john, то john посилається на всю структуру. Для того, щоб отримати доступ до окремих її членів, використовується оператор вибору члена .. Наприклад, в прикладі нижче ми використовуємо оператор вибору членів для ініціалізації кожного члена структури:

Як і у випадку зі звичайними змінними, змінні-члени структури не ініціалізуються автоматично і зазвичай містять сміття. Ініціалізувати їх потрібно вручну.

В наведеному вище прикладі легко визначити, яка змінна відноситься до структури John, а яка — до структури James. Це забезпечує набагато більш високий рівень організації, ніж у випадку зі звичайними окремими змінними.

Змінні-члени структури працюють так само, як і прості змінні, тому з ними можна виконувати звичайні арифметичні операції і операції порівняння:

Ініціалізація структур

Ініціалізація структур шляхом присвоювання значень кожному члену в індивідуальному порядку — заняття досить нудне (особливо, якщо цих членів багато), тому в C++ є більш швидкий спосіб ініціалізації структур — за допомогою списку ініціалізаторів. Він дозволяє ініціалізувати деякі або всі члени структури під час оголошення змінної типу struct:

В C++11 також можна використовувати uniform-ініціалізацію:

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

C++11/14: Ініціалізація нестатичних членів структур

У C++11 додали можливість присвоювати нестатичним (звичайним) членам структури значення за замовчуванням, наприклад:

На жаль, в C++11 синтаксис ініціалізації нестатичних членів структури несумісний з синтаксисом списку ініціалізаторів або uniform-ініціалізацією. У C++11 наступна програма НЕ скомпілюється:

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

Проте в C++14 це обмеження було знято, і обидва варіанти можна використовувати. Ми ще поговоримо детальніше про статичні члени структур у відповідному уроці.

Присвоювання значень членам структур

До C++11, якби ми захотіли присвоювати значення членам структури, то нам би довелося це робити вручну для кожного члену окремо:

Це біль, особливо коли членів в структурі багато. У C++11 ви можете присвоювати значення членам структур, використовуючи список ініціалізаторів:

Структури і функції

Великою перевагою використання структур замість окремих змінних є можливість передати всю структуру в функцію, яка повинна працювати з її членами:

В наведеному вище прикладі ми передали структуру Employee в функцію printInformation(). Це дозволило нам не передавати кожну змінну окремо. Більше того, якщо ми коли-небудь захочемо додати нових членів в структуру Employee, то нам не доведеться змінювати оголошення або виклик функції!

Результат виконання програми:

ID: 21
Age: 27
Salary: 28.45

та:

ID: 22
Age: 29
Salary: 19.29

Функція також може повертати структуру (це один з тих небагатьох випадків, коли функція може повертати декілька змінних), наприклад:

Результат виконання програми:

The point is zero

Вкладені структури

Одні структури можуть містити інші структури, наприклад:

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

Спочатку ми вибираємо поле CEO з структури myCompany, а потім вибираємо поле salary з структури Employee.

Ви можете використовувати вкладені списки ініціалізаторів з вкладеними структурами:

Розмір структур

Як правило, розмір структури — це сума розмірів всіх її членів, але не завжди!

Наприклад, розглянемо структуру Employee. На більшості платформ тип short займає 2 байти, тип int — 4 байти, а тип double — 8 байт. Отже, очікується, що Employee буде займати 2 + 4 + 8 = 14 байт. Щоб дізнатися точний розмір Employee, ми можемо скористатися оператором sizeof:

Результат виконання програми (на моєму комп’ютері):

The size of Employee is 16

Виявляється, ми можемо сказати тільки, що розмір структури буде, принаймні, не менше суми розмірів всіх її членів. Але він може бути і більше! З міркувань продуктивності компілятор іноді може додавати “пробіли” в структури.

У структурі Employee компілятор неявно додав 2 байти після члену id, збільшуючи розмір структури до 16 байтів (замість 14). Пояснення причини, через яку це відбувається, — виходить за рамки цього туторіалу, але якщо ви хочете знати більше, то можете прочитати про вирівнювання даних у Вікіпедії.

Доступ до структур з декількох файлів

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

Змінні типу struct підкоряються тим же правилам, що і звичайні змінні. Отже, якщо ви хочете зробити змінну структури доступною в декількох файлах, то ви можете використати ключове слово extern.

Висновки

Структури дуже важливі в C++, оскільки їх розуміння — це перший великий крок до об’єктно-орієнтованого програмування! Пізніше, в цих уроках, ви дізнаєтеся про ще один користувацький тип даних — клас, який є продовженням теми структур.

Тест

Завдання №1

У вас є веб-сайт і ви хочете відстежувати, скільки грошей ви заробляєте в день від розміщеної на ньому реклами. Оголосіть структуру Advertising, яка буде відслідковувати:

   скільки оголошень ви показали відвідувачам (1);

   скільки відсотків відвідувачів натиснули на оголошення (2);

   скільки ви заробили в середньому за кожен клік по оголошенню (3).

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

Відповідь №1

Завдання №2

Створіть структуру для зберігання дробових чисел. Структура повинна мати 2 члена: цілочисельний чисельник і цілочисельний знаменник. Оголосіть дві дробові змінні і отримайте їх значення від користувача. Напишіть функцію multiply() (параметрами якої будуть ці дві змінні), яка перемножить ці числа і виведе результат у вигляді десяткового числа.

Відповідь №2

Оцінити статтю:

1 Зірка2 Зірки3 Зірки4 Зірки5 Зірок (1 оцінок, середня: 5,00 з 5)
Loading...

Залишити відповідь

Ваш E-mail не буде опублікований. Обов'язкові поля відмічені *