Как вы передаете производный класс, если вы знаете только базовый класс?

0

Я заранее прошу прощения, поскольку я начинаю программировать OO.

У меня есть базовый класс Hero, с тремя производными классами Archer, Warrior и Mage. Пользователю предлагается выбрать один из них и создать объект соответствующего производного класса. Они имеют разные начальные значения и функции-члены, а следующий шаг - передать этот объект другой функции.

Скажем, функция называется battle(), и она принимает объект в качестве аргумента. Как мне это сделать? Должен ли я создать три отдельных боя() или есть способ передать объект без необходимости определять производный класс?

void Hero::init(string job)
{  
    if (job == "archer")
        Archer archer;
    else if (job == "mage")
        Mage mage;
    else
        Warrior warrior;

    battle(); // What to put as argument?
}
Теги:
class
object

3 ответа

3
Лучший ответ

battle() должен использовать ссылочный или (умный) указатель на базовый класс в качестве аргумента. Например:

void battle(std::shared_ptr<Hero> ptr);

И ваш аргумент должен быть умным указателем:

void Hero::init(const std::string& job)
{
    std::shared_ptr<Hero> ptr;

    if (job == "archer")
        ptr = std::make_shared<Archer>();
    else if (job == "mage")
        ptr = std::make_shared<Mage>();
    else
        ptr = std::make_shared<Warrior>();

    battle(ptr);
}

std::shared_ptr - класс интеллектуальных указателей, который инкапсулирует распределение динамической памяти и сбор ресурсов для указателя. Это связано с тем, что мы не должны писать new повсюду. Более того, когда умный указатель уничтожается (это означает, что не существует больше копий ptr, если они есть), то delete вызывается в содержащемся указателе Hero.

Вышеизложенное работает, потому что все три класса производны от Hero так что адреса этих указателей на производные классы могут быть указаны базовым классом.

  • 0
    std :: shared_ptr и std :: make_shared не компилируются. Я использую последнюю версию Code Blocks.
  • 1
    @geft Вам нужно #include файл <memory> .
3

Нет, вам не нужно создавать 3 разных battle задания, избегая этого, это как раз и цель наследования.

Вы можете создать единую battle функцию:

void battle(Hero& hero)
{
}

Вы можете назвать это следующим образом:

battle(archer);
battle(mage);
battle(warrior);

но вам нужно будет создать Heros по - другому, потому что, как они создаются в настоящее время, они выпадают из сферы, как только if или else сделано.

  • 0
    Спасибо, но что значит Hero& ? Я не знаком с концепцией.
  • 1
    Это ссылка. Это означает, что вы работаете с объектом, созданным вне функции сражения.
2

Здесь вы должны использовать полиморфизм во время выполнения.
Вместо создания локальных экземпляров объекта производного класса создайте указатель базового класса и укажите его на экземпляр производного класса:

Hero* hero = new Archer();
Hero* hero = new Mage();
Hero* hero = new Warrior();

Затем вы можете передать указатель базового класса Hero* вашему методу battle

battle(hero)  

Подпись вашего метода:

void battle(Hero* )  

Это означает, что метод боя может принимать любого героя во время выполнения, будь то лучник, маг или воин.

  • 1
    Это все еще создает производные экземпляры объекта класса.
  • 0
    Перефразировал предложение.
Показать ещё 2 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню