Умные указатели и полиморфизм - использование в модельном классе вызывает проблемы с литьемC++

Программы на C++. Форум разработчиков
Ответить Пред. темаСлед. тема
Anonymous
 Умные указатели и полиморфизм - использование в модельном классе вызывает проблемы с литьем

Сообщение Anonymous »

Я пытаюсь сделать игру в C ++, где произведения будут перемещаться по игре. C ++ 11 принес с собой, включая умные указатели. Но эта ржавость заставляет нас возникать некоторыми проблемами с полиморфизмом. Мы смотрим на C ++ 20, но мы еще не там, поэтому, хотя решения, связанные с этим, в порядке, как будущее, нам действительно нужен метод C ++ 17. Мы моделируем Gameboard в памяти, используя выбор контейнеров, представляющих различные места в игре, такие как палубы, «в игре», рынок и т. Д. PrettyPrint-Override ">

Код: Выделить всё

GameInstance
- AbilityHealthInstance
- PlayerAvatarInstance
- MonsterCardInstance - multi inherit
- CardInstance
- MonsterCardInstance - multi inherit
- SpellCardInstance
- TokenInstance
В настоящее время мы используем std :: ulious_ptr для представления каждого экземпляра GameInstance , размещая их в разных коллекциях, чтобы представлять различные области модели Gameboard, используя STD :: Move> для перемещения из одного списка в другой. Список std :: ulious_ptr
[*] Discard - Список std :: unique_ptr
[*] Market - список std :: ulious_ptr std :: ulious_ptr

[*] Поле - массив фиксированного размера std :: ulious_ptr
[*] Active - список std :: unique_ptr

/> Итак, в начале игры мы строим палубы, создавая каждую карту в качестве соответствующего типа, вызывая emplace_back и кормляем при вызове std :: make_unique () или std :: make_unique () в зависимости от. Рынок заполнен от колоды, чтобы игрок мог купить. Никаких проблем здесь, колода и рынок - это то же самое кардинстенс тип. Мы все немного смущены, это не позволяет использовать его, чтобы использовать его, как мы ожидаем. />
Чтобы достичь этого, я хочу снять из std :: ulious_ptr на std :: ulious_ptr , как я бы, если бы я использовал необработанные указатели и dynamic_cast . Таким образом, я могу определить построенный тип, затем переместить экземпляр в коллекцию, к которой он должен перейти, чтобы представить место на игровой доске. Проблема в том, что я не могу найти std :: ulious_ptr эквивалент std :: dynamic_pointer_cast , который, как я нашел, существовал для std :: shared_ptr

Код: Выделить всё

bool BuyCard(size_t idx)
{
//find a free spot in the field and attempt to move the card there if it's a monster
auto newPos = std::find_if(Field.begin(), Field.end(), [&mktref, &index, iTargets](std::unique_ptr& fldref ) {
if (fldref == nullptr)
{
//unique_pointer_cast is some equivalent for dynamic_cast in this instance
fldref = unique_pointer_cast(std::move(mktref));
return fldref == nullptr; //assume unique_pointer_cast would return null if cast impossible
}
index++;
return false;
});
if (newpos != Field.end())
{
return true; //buy monster worked
}
else
{
//wasn't a monster, put the card to the back of the active cards as we can assume it was a spell
Active.emplace_back(unique_pointer_cast(std::move(mktref));
return Active.back() != nullptr; //lets hope the buy spell worked
}
}
Аналогичные проблемы возникают, если я попытаюсь, чтобы функция использовала функциональность MonsterCardinstance и PlayerAvatarinStance поделиться через способность hipealthInstance . Если бы я использовал необработанные указатели, я бы передал любой объект в параметр функции, который принял бы указатель ebilityHealthInstance . Я не могу выглядеть, когда я смотрю на std :: ulious_ptr или std :: ulious_ptr Пытаться перейти в std :: unique_ptr & .

Код: Выделить всё

bool DamageCard(unique_ptr target, size_t damage)
{
target->TakeDamage(damage)
if (target->isDead())
{
//move to discard
}
}
//won't allow the following
DamageCard(PlayerAvatar, 5);
DamageCard(Field[3], 5);
< /code>
Что я ошибаюсь с использованием умных указателей здесь? Как я и предполагаю, мне либо упускаю трюк, либо недоразумю их вариант использования. Но остаются вопросы полиморфизма.  Хотя я благодарен за то, что они помечали его, так как это означало, что мы вернулись и посмотрели < /p>
GameInstance
- PlayerAvatarInstance
- CardInstance
- MonsterCardInstance
- SpellCardInstance
- TokenInstance
AbilityHealthInterface
- PlayerAvatarInstance
- MonsterCardInstance
Ключевое, что люди говорят, - это std :: inistance_ptr о владении, и это правильно, область на гайке, в которой находится элемент, владеет этим элементом. Идея состоит в том, чтобы заставить ход, чтобы указатель на один и тот же экземпляр не мог существовать в двух местах одновременно. Если бы я использовал std :: shared_ptr или необработанные указатели, они могли бы быть легко скопированы в пункт назначения без удаления из источника. Идея состоит в том, чтобы обеспечить соблюдение того, что если карта перемещается от одной коллекции, представляющей область игры в другую, она должна использовать STD :: Move , чтобы предотвратить вышеупомянутые ошибки/ошибки. Учитывая, что теперь мы полностью осознаем, что владельцы являются объектами std :: vector , а не класс, который я пишу, и в комментариях снова упоминаются варианты дизайна, он заставил взглянуть на то, как было написано некоторые вещи. Таким образом, сами экземпляры были перемещены некоторые функциональности. /> Что касается изменений в собственном владении, я обнаружил пример static_unique_pointer_cast < /code> в альтернативах static_pointer_cast для уникального_птра, который решает проблему, но все же смущает нас в целом относительно того, почему необходимо вращать нашу собственную. Насколько я знал, std :: ulious_ptr был предназначен для очистки объекта, когда владелец вышел из области, в котором ничего не говорит о том, что невозможно сохранить разные объекты одного и того же базового класса в одном и том же месте, которое может измениться на основе функциональности
, где я использую необработанные указатели, которые в более современном языке я хочу использовать STD :: ulious_ptr

Подробнее здесь: https://stackoverflow.com/questions/796 ... ing-issues
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «C++»