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

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

Сообщение Anonymous »

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

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

GameInstance
- PlayerAvatarInstance
- CardInstance
- MonsterCardInstance
- SpellCardInstance
- TokenInstance
AbilityHealthInterface (pure virtual)
- PlayerAvatarInstance
- MonsterCardInstance
В настоящее время мы используем std :: ulious_ptr для представления каждого экземпляра GameInstance , размещая их в разных коллекциях, чтобы представлять различные области модели Gameboard, используя STD :: Move> для перемещения из одного списка в другой. std :: ecector
[*] Discard - a std :: vector
[*] Market - a Std :: array
Чтобы достичь этого, я хочу снять из std :: ulious_ptr на std :: ulious_ptr , как я бы, если бы я использовал необработанные указатели и dynamic_cast . Таким образом, я могу определить построенный тип, потенциально опираясь на какой -то метод обнаружения плохого актера (например, я получу Nullptr от того, чтобы перенести экземпляр в коллекцию, к которому необходимо перейти, чтобы представить место на игровой доске. Проблема заключается в 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));
if (Active.back() != nullptr) //lets hope the buy spell worked
{
//now it's been cast, I can access SpellCardInstance methods
Active.back()->ActivateSpell();
return true;
}
}
return false;
}
Так как я могу переместить экземпляр std :: ulious_ptr из одного места в другое, где я знаю, что обернутый объект сможет идти? Это включает в себя оба иллюстрированные варианты использования: определяющий тип для отбрасывания и майки, а также доступ к функциям членов может иметь полученный класс, но база нет. < /P>

аналогичные проблемы возникают, если я пытаюсь выполнить функцию, используя функциональность, которые различные области разделяют через общий родитель, в частности, в том же духе, что он относится к использованию в качестве параметра, передаваемого в соответствии с пропущенным в качестве параметра. Важно отметить, что я не хочу перемещать карты при этом, но потенциально выполнять одну и ту же операцию, так что это также может быть лямбда в рамках одной и той же функции, которая внедряется в разных областях. < /P>

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

MonsterCardInstance
и playeravatarinstance поделиться функциональностью через ebilityhealthinstance . Если бы я использовал необработанные указатели, я бы передал любой объект в параметр, который принял бы указатель ebilityHealthInstance . Я не могу выглядеть, когда я смотрю на std :: ulious_ptr или std :: ulious_ptr Пытаться перейти в std :: unique_ptr & parameter.

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

bool DamageCard(unique_ptr& target, size_t damage)
{
target->TakeDamage(damage)
if (target->isDead())
{
target->onDeath()
}
}
//won't allow the following
DamageCard(PlayerAvatar, 5);
DamageCard(Field[3], 5);

// Or use in a lambda, which is a more common occurrence given I'm trying to use  functionality as much as I can

void DamageAll(size_t damage)
{
auto doDamage=[&](std::unique_ptr& target){
target->TakeDamage(damage)
if (target->isDead())
{
target->onDeath()
}
};
std::for_each(Field.begin(), Field.end(), doDamage);
doDamage(PlayerAvatar)
}
//so instead it needs to be written as such, duplicating some code

void DamageAll(size_t damage)
{
auto doDamage=[&](std::unique_ptr& target){
target->TakeDamage(damage)
if (target->isDead())
{
target->onDeath();
}
};
std::for_each(Field.begin(), Field.end(), doDamage);
PlayerAvatar->TakeDamage(damage)
if (PlayerAvatar->isDead())
{
PlayerAvatar->onDeath();
}
}
< /code>

Во всех этих случаях мы знаем о std :: ulious_ptr :: get () < /code> потенциально является решением, но даже это не помогает в случае использования лямбдас в функциях  < /code>. Это еще одна точка путаницы для нас: мы ожидаем просто использовать объект, который у нас есть, как если бы мы использовали необработанный указатель, не нуждающийся в том, чтобы получить необработанное указатель, чтобы полностью его использовать. Это похоже на достаточно реальный вариант использования для полиморфизма, который, как мы ожидали, std :: ulious_ptr 
для поддержания изначально. Поскольку я предполагаю, что эти камни преткновения означают>

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

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

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

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

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

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

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