Розділ №11. Підсумковий тест

  Юрій  | 

  Оновл. 28 Лют 2021  | 

 57

У цьому розділі ми розглянули спадкування в мові C++. Пора закріпити пройдений матеріал.

Теорія

Спадкування дозволяє моделювати відносини типу «є» між двома об’єктами. Об’єкт, який наслідує, називається дочірнім класом. Об’єкт, якого наслідують, називається батьківським класом.

При спадкуванні дочірній клас наслідує всі члени батьківського класу.

При ініціалізації об’єктів дочірнього класу, спочатку виконується побудова батьківської частини об’єкта, а потім вже дочірньої частини об’єкта. Розглянемо детально:

   Спочатку виділяється пам’ять для об’єкта дочірнього класу (достатня порція для 2-х частин, з яких складається об’єкт: батьківська і дочірня).

   Викликається відповідний конструктор дочірнього класу.

   Виконується побудова батьківської частини з використанням відповідного конструктора батьківського класу. Якщо конструктор не вказано, то використовується конструктор за замовчуванням батьківського класу.

   Список ініціалізації дочірнього класу ініціалізує члени дочірнього класу.

   Виконується тіло конструктора дочірнього класу.

   Керування повертається назад в caller.

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

Мова C++ має 3 специфікатори доступу: public, private і protected. Специфікатор protected використовується для дозволу доступу до членів дружнім класам/функціям і дочірнім класам, всім іншим об’єктам — доступ закритий.

Є 3 типи спадкування: public, private і protected. Найбільш поширений тип спадкування — public.

Таблиця специфікаторів доступу і типів спадкування:

Специфікатор доступу в батьківському класі Специфікатор доступу при спадкуванні типу public в дочірньому класі Специфікатор доступу при спадкуванні типу private в дочірньому класі Специфікатор доступу при спадкуванні типу protected в дочірньому класі
public public private protected
private Недоступний Недоступний Недоступний
protected protected private protected

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

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

Тест

Завдання №1

Для кожної з наступних програм визначте результат виконання. Якщо програма не скомпілюється, то поясніть чому. Запускати код не потрібно, ви повинні визначити результат/помилки програм без допомоги компілятора.

a)

Відповідь №1.a)

Спочатку ініціалізується батьківська частина об’єкту, а потім вже дочірня. Знищення відбувається в зворотному порядку.

Parent()
Child()
~Child()
~Parent()

b)

Підказка: Локальні змінні знищуються в порядку протилежному визначенню.

Відповідь №1.b)

Спочатку виконується побудова ch:

Parent()
Child()

Потім побудова p:

Parent()

Потім знищення p:

~Parent()

Потім знищення ch:

~Child()
~Parent()

c)

Відповідь №1.c)

Не скомпілюється. Метод Child::print() не має доступу до закритого члену m_x.

d)

Відповідь №1.d)

Результат:

Parent()
Child()
Child: 7
~Child()
~Parent()

e)

Відповідь №1.e)

Результат:

Parent()
Child()
D2()
Child: 7
~D2()
~Child()
~Parent()

Завдання №2

a) Створіть класи Apple і Banana, які наслідують клас Fruit. У класі Fruit є дві змінні-члени: name і color.

Наступний код:

Повинен видавати наступний результат:

My apple is red.
My banana is yellow.

Відповідь №2.a)

b) Додайте новий клас GrannySmith, який наслідує клас Apple.

Наступний код:

Повинен видавати наступний результат:

My apple is red.
My banana is yellow.
My Granny Smith apple is green.

Відповідь №2.b)

Завдання №3

Найулюбленіше! Будемо створювати просту гру, в якій ви будете битися з монстрами. Ціль гри — зібрати максимум золота, перш ніж ви помрете або досягнете 20 рівня.

Гра складається з 3-х класів: Creature, Player і Monster. Player і Monster наслідують клас Creature.

a) Спочатку створіть клас Creature з наступними членами:

   ім’я (std::string);

   символ (char);

   кількість здоров’я (int);

   кількість ушкодження, яке він наносить ворогу під час атаки (int);

   кількість золота, яке він має (int).

Створіть повний набір геттерів (по одному на кожну змінну-член класу). Додайте ще три методи:

   void reduceHealth(int) — зменшує здоров’я Creature на вказане цілочисельне значення;

   bool isDead() — повертає true, якщо здоров’я Creature дорівнює 0 або менше;

   void addGold(int) — додає золото Creature-у.

Наступний код:

Повинен видавати наступний результат:

The orc has 3 health and is carrying 15 gold.

Відповідь №3.a)

b) Тепер нам потрібно створити клас Player, який наслідує Creature. Player має:

   змінну-член level, яка починається з 1;

   ім’я (користувач вводить з клавіатури);

   символ @;

   10 очків здоров’я;

   1 очко ушкодження (для початку);

   0 золота.

Напишіть метод levelUp(), який збільшує рівень Player-а і його ушкодження на 1. Також напишіть геттер для члену level і метод hasWon(), який повертає true, якщо Player досяг 20 рівня.

Додайте в функцію main() код, який запитує у користувача його ім’я і виводить кількість його здоров’я і золота:

Enter your name: Anton
Welcome, Anton.
You have 10 health and are carrying 0 gold.

Відповідь №3.b)

c) Наступний клас Monster також наслідує Creature і у нього немає власних змінних-членів. Але є перерахування Type, яке містить 3 енумератора, вони позначають типи монстрів: DRAGON, ORC і SLIME (вам також потрібен додатковий енумератор MAX_TYPES).

Відповідь №3.c)

d) Кожен тип Монстра має своє ім’я, символ, певну кількість здоров’я, ушкодження і золота:

Type Name Symbol Health Damage Gold
DRAGON dragon D 20 4 100
ORC orc o 4 2 25
SLIME slime s 1 1 10

Наступний крок — реалізація конструктора класу Monster, за допомогою якого можна створювати монстрів. Цей конструктор повинен приймати перерахування Type в якості параметру, а потім створювати монстра з відповідними таблиці характеристиками.

Це можна реалізувати по-різному. Однак, оскільки всі наші властивості типів монстрів визначені (не випадково), ми можемо використовувати таблицю пошуку. Таблиця пошуку — це масив, який містить усі визначені атрибути (властивості) будь-чого. Ми можемо використовувати таблицю пошуку для перегляду характеристик певного типу монстра по мірі необхідності.

Як це зробити? Нам потрібні всього лише дві речі. По-перше, масив з окремим елементом для кожного типу монстра. По-друге, цей елемент міститиме структуру, в якій будуть знаходитися всі визначені значення атрибутів для конкретного типу монстра.

   Крок №1: Створіть структуру MonsterData всередині класу Monster. Ця структура повинна мати наступні енумератори: name, symbol, health, damage і gold.

   Крок №2: Оголосіть статичний масив цієї структури з іменем monsterData.

   Крок №3: Додайте код визначення нашої таблиці пошуку поза тілом класу:

Тепер ми можемо шукати будь-які значення, які нам потрібні! Наприклад, щоб дізнатися кількість золота Dragon, ми можемо використати monsterData[DRAGON].gold.

Використовуйте цю таблицю пошуку для реалізації вашого конструктора:

Наступний код:

Повинен видавати наступний результат:

A orc (o) was created.

Відповідь №3.d)

e) Нарешті, додайте статичний метод getRandomMonster() в клас Monster. Цей метод повинен генерувати випадкове число від 0 до MAX_TYPES-1 і повертати (повернення по значенню) певний тип монстра (вам потрібно використати оператор static_cast для конвертації int в Type, щоб передати його конструктору класу Monster).

Ви можете використовувати наступний код для генерації випадкового числа:

Наступний код:

Повинен згенерувати 10 рандомних монстрів:

A slime (s) was created.
A orc (o) was created.
A slime (s) was created.
A slime (s) was created.
A orc (o) was created.
A orc (o) was created.
A dragon (D) was created.
A slime (s) was created.
A orc (o) was created.
A orc (o) was created.

Відповідь №3.e)

f) Готово, тепер нам потрібно розібратися з логікою нашої гри!

Суть:

   Гравець стикається з одним випадково вибраним монстром.

   З кожним монстром гравець може або (R)un, або (F)ight.

   Якщо гравець вирішує Run, то шанси на вдалу втечу складають 50%.

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

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

   Якщо гравець вибирає Fight, то він атакує монстра. Здоров’я монстра зменшується від ушкодження гравця.

   Якщо монстр вмирає, то гравець забирає все золото монстра + збільшує свій level і ушкодження на 1.

   Якщо монстр не вмирає, то він атакує гравця. Здоров’я гравця зменшується від ушкодження монстра.

   Гра закінчується, якщо гравець загинув (програш) або досяг 20 рівня (виграш).

   Якщо гравець вмирає, то програма повинна повідомити гравцеві, який рівень у нього був і скільки золота він мав.

   Якщо гравець перемагає, то гра повинна повідомити гравцеві, що він виграв і скільки у нього є золота.

Приклад гри:

Enter your name: Anton
Welcome, Anton
You have encountered a orc (o).
(R)un or (F)ight: r
You successfully fled.
You have encountered a slime (s).
(R)un or (F)ight: f
You hit the slime for 1 damage.
You killed the slime.
You are now level 2.
You found 10 gold.
You have encountered a dragon (D).
(R)un or (F)ight: f
You hit the dragon for 2 damage.
The dragon hit you for 4 damage.
(R)un or (F)ight: f
You hit the dragon for 2 damage.
The dragon hit you for 4 damage.
(R)un or (F)ight: f
You hit the dragon for 2 damage.
The dragon hit you for 4 damage.
You died at level 2 and with 10 gold.
Too bad you can't take it with you!

Підказка: У вас повинні бути наступні 4 функції:

   Функція створення Гравця і основний ігровий цикл (в функції main()).

   Функція fightMonster(), яка обробляє бій між Гравцем і Монстром, і запитує у гравця, що він хоче зробити: Run чи Fight.

   Функція attackMonster(), яка обробляє атаку монстра гравцем, включаючи збільшення рівня гравця.

   Функція attackPlayer(), яка обробляє атаку гравця монстром.

Відповідь №3.f)

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

1 Зірка2 Зірки3 Зірки4 Зірки5 Зірок (Немає Оцінок)
Loading...

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

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