Глава №11. Итоговый тест

   | 

   | 

 Обновлено 9 Окт 2018  | 

 556

В этой главе мы рассмотрели наследование в 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

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

1a)

Ответ 1a)

Сначала инициализируется родительская часть объекта, а затем уже дочерняя. Уничтожение происходит в обратном порядке.

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

1b)

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

Ответ 1b)

Сначала выполняется построение d:

Parent()
Child()

Затем построение b:

Parent()

Затем уничтожение b:

~Parent()

Затем уничтожение d:

~Child()
~Parent()

1c)

Ответ 1c)

Не скомпилируется. Child::print() не имеет доступа к закрытому члену m_x.

1d)

Ответ 1d)

Результат:

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

1e)

Ответ 1e)

Результат:

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

Задание №2

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

Следующий код:

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

My apple is red.
My banana is yellow.

Ответ 2a)

2b) Добавьте новый класс GrannySmith, который наследует класс Apple.

Следующий код:

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

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

Ответ 2b)

Задание №3

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

Игра состоит из 3 классов: Creature, Player и Monster. Player и Monster наследуют класс Creature.

3a) Сначала создайте класс 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.

Ответ 3a)

3b) Теперь нам нужно создать класс 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.

Ответ 3b)

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

Ответ 3c)

3d) Каждый тип Монстра имеет своё имя, символ, определенное количество здоровья, урона и золота:

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.

Ответ 3d)

3e) Наконец, добавьте статический метод 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.

Ответ 3e)

3f) Готово, теперь нам нужно разобраться с логикой выполнения нашей игры!

Суть:

   Игрок сталкивается с одним случайно выбранным монстром.

   С каждым монстром игрок может либо (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() обрабатывает атаку монстра игроком, включая увеличение level-а игрока.

   attackPlayer() обрабатывает атаку игрока монстром.

Ответ 3f)

Оценить статью:

Звёзд: 1Звёзд: 2Звёзд: 3Звёзд: 4Звёзд: 5 (4 оценок, среднее: 4,75 из 5)
Загрузка...
Подписаться на обновления:

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

ВОЛШЕБНАЯ ТАБЛЕТКА ПО С++