Переключение между разными типами указателей на объекты

До сих пор я использовал динамическое приведение. Но это имеет свои плюсы и минусы. Кажется, это хорошая вещь, НЕ использовать это слишком много. Примеры по этой теме, которые я нашел, обычно с классами, которые имеют небольшие различия. Но в моем случае у «детских» классов очень мало общего.

Код в этом посте НЕ из проекта. Он используется только для примера.

Я делаю торговую систему для игры, и в проекте будет еще много систем. Есть много разных предметов, которые делают много разных вещей — оборудование, модификации, ресурсы. Независимо от того, насколько они различны, у всех них есть цена, и все они могут быть помещены в инвентарь, независимо от того, что они. Но на этом сходство заканчивается, включая переопределенные методы.

После этого разные предметы используются совершенно по-разному. Сначала разные типы предметов сортировались в отдельных массивах указателей разных типов — один для оборудования, один для модификаций, например, т. Д. Чтобы положить что-то в инвентарь, я использую только один метод: addToInventory(Item* item) , Поскольку элемент должен быть помещен в правильный массив, я использую динамическое приведение Item* item к (например) Equipment* equiтак что я могу добавить его в массив оборудования. Я хочу сделать это одним и тем же методом, потому что он более интуитивно понятен, в противном случае разные методы будут иметь похожий код

addToInventory(Item* item)
{
if (item->type == 'e')
{
Equipment* newEquip = dynamic_cast<Equipment*>(item);
equipmentArr.add(newEquip);//thous arrays are dynamic- the reason I needed to make the conversion explained later
}
else if (item->type == 'm')
{
Modification* newMod = dynamic_cast<Modification*>(item);
modificationArr.add(newEquip);
}
//and so on...
}

Позже я хотел бы добавить модификацию к элементу оборудования Weapon::addMod(Modification* mod) , И в этом методе я использую другие методы и переменные, которые находятся ТОЛЬКО в классе оружия.

addMod (Modification* mod)
{//all are found ONLY in class Weapon
mod[modCount] = mod; //an array of Modification* pointers
modCount++;
calcEfficiency();
}

Но когда я хочу сделать простую вещь для печати инвентаря, мне нужно либо скопировать-вставить и отредактировать некоторый код для преобразования указателей в массивах, чтобы я мог передать их тем же способом печати, или скопировать-вставить и редактировать тот же код для печати. Существует третий вариант — сделать массивы для всех массивов указателей на объекты Item. Я попробовал последний вариант.

Избавился от кастинга в addToInventory(Item* item), ура! Но это вызвало необходимость использовать приведение КАЖДЫЙ раз, когда мне нужно вызывать такие методы, как Weapon::addMod(Modification* mod) и в других местах. В противном случае мне нужно будет поместить приведение в метод, но я хочу, чтобы метод явно Equipment* аргумент.

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

Итак, в аналогичном случае, как я должен переключаться между различными типами указателей?

0

Решение

Вы можете представлять черты (а именно Equipment а также Modification) вашего (широкого) Item реализации как чистые виртуальные классы (то есть интерфейсы). Таким образом, динамическое приведение и проверка динамического приведение для этих интерфейсов в порядке и уменьшит шум для обработки для реальных реализаций Equipment а также Modification,

Другой способ заключается в использовании Шаблон CRTP а также static_cast<Interface*> иметь проверки времени компиляции для ваших интерфейсов.

Зависит от вашего варианта использования, какой способ является более подходящим. Как правило большого пальца:

  • В основном статическая конфигурация => Делать во время компиляции
  • Более динамическая конфигурация (экземпляры, выделенные во время выполнения) => Делать во время выполнения
1

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


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