Шаблоны здесь не тот инструмент. Полиморфизм.
Шаблоны полезны, когда у вас есть похожий или идентичный код, который должен работать с несколькими несвязанными типами. Полиморфизм полезен, когда у вас есть набор напрямую связанных типов, каждый из которых должен делать разные вещи.
Здесь у вас есть крестоносцы, герои и монстры, каждый из которых атакует, получает урон и перемещается по-разному, но также все разные подразделения, то есть все они напрямую связаны и попадают во вторую категория.
Итак, с теорией все в порядке, но нас больше интересует реализация, а не теория ...
Чтобы решить проблему, вам нужно сделать два исправления. делать.
Во-первых, определения классов неверны в том виде, в каком они написаны - нам не нужны какие-либо шаблоны, чтобы мы могли избавиться от всего этого.
class Unit
{
public:
Unit();
virtual ~Unit();
virtual void Attack(std::shared_ptr<Unit> Target, const AttackSkill& skill);
};
...
class Hero : public Unit
{
public:
Hero();
virtual ~Hero();
virtual void Attack(std::shared_ptr<Unit> Target, const AttackSkill& Skill) override;
};
...
class Crusader : public Hero
{
public:
Crusader();
~Crusader();
void Attack(std::shared_ptr<Unit> Target, const AttackSkill& Skill);
};
Здесь я ' m при условии, что у Crusader нет подклассов - если есть, убедитесь, что деструктор и Attack()
оба виртуальны.
Теперь второе важное изменение - это ваши методы сбора и вставки:
std::vector<std::shared_ptr<Unit>> Units;
...
Units.emplace_back(std::make_shared(new Crusader());
Основное отличие здесь - использование указателей. Полиморфизм в C ++ в основном требует, чтобы вы использовали указатели - использование простых объектов без указателей заставит компилятор "разрезать" ваш класс, удалив любое ваше настраиваемое поведение. Это становится серьезной проблемой, если, скажем, вы добавляете модификатор святости в качестве члена класса Crusader, а затем пытаетесь получить к нему доступ из «нарезанного» класса - программа немедленно взломает sh, потому что «нарезка» удаляет все, чего нет в базовый класс объекта.
Чтобы сделать их немного «удобнее», я заключил указатели здесь в std::shared_ptr
. Это обеспечивает автоматический c подсчет и уничтожение ссылок, когда ссылок больше нет. Однако те же правила применяются независимо от того, используете ли вы std::shared_ptr
или необработанные указатели.