Один контейнер различных объектов, которые все унаследовали один и тот же класс

Я пытаюсь что-то сделать, но не уверен, возможно ли это.

Идея в том, что я пишу игру и хочу иметь один массив (или вектор) разных монстров. Каждый класс, который наследует основной класс Monster, просто переопределяет его функции (но не добавляет новых).

Затем, когда я просматриваю список монстров, я могу просто вызывать те же функции, что и у всех.

Вот некоторый код, чтобы показать, что я пытаюсь сделать:

class Monster
{
public:
int hp;  //hit points
int atp; //attack power
int def; //defense

bool attacking;
bool defending;

virtual void attack();
virtual void defend();
};

void Monster::attack()
{}

void Monster::defend()
{}class Goblin: public Monster
{
public:
virtual void attack() override;
virtual void defend() override;
};

void Goblin::attack()
{
//Goblin's attacking patterns
}

void Goblin::defend()
{
//Goblin's defending patterns
}class Orc: public Monster
{
public:
virtual void attack() override;
virtual void defend() override;
};

void Orc::attack()
{
//Orc's attacking patterns
}

void Orc::defend()
{
//Orc's defending patterns
}int main(void)
{
//This is where I'm not sure what to do:

//Initialize monsters.  Make some Goblins, some Orcs
int num_monsters = 10;
Monster* monster_list;
monster_list = new Monster[num_monsters];

for (int i = 0; i < num_monsters; i++)
{
int which = rand() % 2;
switch (which)
{
case 0:  //Goblin
monster_list[i] = new Goblin;
break;
case 1:  //Orc
monster_list[i] = new Orc;
break;
}
}

bool quit = false;
while (quit == false)
{
for (int i = 0; i < num_monsters; i++)
{
if (monster_list[i].attacking == true)
monster_list[i].attack();
if (monster_list[i].defending == true)
monster_list[i].defend();
}
}
}

Надеюсь, это иллюстрирует то, что я пытаюсь сделать.
Я знаю, что это не работает, но я не уверен, как заставить это работать.
Спасибо за любой совет по этому поводу!

1

Решение

Вам нужно будет использовать вектор указателей на базовый класс.

std::vector<Monster*> monsters;

monsters.push_back(new FireDragon());
monsters.push_back(new IceDragon());

Тогда вы сможете перебирать вектор монстров и вызывать общий метод.

for(auto monster = monsters.begin(); monster != monsters.end(); monster++)
{
(*monster)->attack();
}

Классы:

class Monster {
public:
virtual ~Monster() {}
virtual void attack() = 0;
};

class FireDragon : public Monster {
public:
~FireDragon();
void attack()
{
std::cout << "Fire breath!" << std::endl;
}
};

class IceDragon : public Monster {
public:
~IceDragon();
void attack()
{
std::cout << "Ice breath!" << std::endl;
}
};

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

ETA: Вот реализация с умными указателями:

/*
Use std::unique_ptr<Monster> if your implementation doesn't need to pass the
monster objects around
*/

std::vector<std::shared_ptr<Monster>> monsters;

/*
Use std::make_unique<FireDragon>() if using unique_ptr
*/

monsters.push_back(std::make_shared<FireDragon>());
monsters.push_back(std::make_shared<IceDragon>());

for(auto monster : monsters)
{
monster->attack();
}
6

Другие решения


По вопросам рекламы [email protected]