Я писал систему компонент-сущность и столкнулся с тем, что должно быть общей проблемой: компонентами, которые зависят друг от друга.Я буду использовать пример:
Скажем, вы создаете компонент элемента, который содержит данные, общие для элементов (скажем, вес).Но тогда, что, если вы хотите сделать компонент оборудования?Любой элемент оборудования также ДОЛЖЕН быть элементом, поэтому у вас будет два зависимых компонента.Такого рода отношения казались подходящими для наследования, поэтому я создал наследующий компонент.
Вопрос в том, что мне теперь нужно два «слоя полиморфизма» и система тегов перечисления, которую я написалбольше не работаетКроме того, я, возможно, захочу позже разделить этот компонент оборудования на несколько типов.
#include <memory>
#include <map>
enum COMPONENT_TAG {
COMP_BASE,
COMP_ITEM,
COMP_ITEM_EQUIP
};
struct VirtualBaseComponent { // component
COMPONENT_TAG tag;
virtual ~VirtualBaseComponent() = 0;
};
VirtualBaseComponent::~VirtualBaseComponent() {};
struct ItemComponent : public VirtualBaseComponent {
COMPONENT_TAG tag = COMP_ITEM;
~ItemComponent() {};
};
struct EquipmentComponent : public ItemComponent {
COMPONENT_TAG tag = COMP_ITEM_EQUIP;
~EquipmentComponent() {};
};
struct Entity {
std::map<COMPONENT_TAG, std::unique_ptr<VirtualBaseComponent>> components;
template <typename T>
T* get_component(COMPONENT_TAG tag) {
auto found = components.find(tag);
VirtualBaseComponent* baseptr;
if (found == components.end()) {
baseptr = nullptr;
} else {
baseptr = found->second.get();
}
return dynamic_cast<T*>(baseptr);
}
};
int main() {
{
//set up a random item (a box)
Entity box;
box.components.insert(std::make_pair(COMP_ITEM, std::make_unique<ItemComponent>()));
//fetching a base component: ok, this works fine
ItemComponent *boxptr = box.get_component<ItemComponent>(COMP_ITEM);
//do_stuff(boxptr->item_property);
}
{// set up a sword
Entity sword;
sword.components.insert(std::make_pair(COMP_ITEM_EQUIP, std::make_unique<EquipmentComponent>()));
//but here, if I actually want to use some "item property" of the sword not related to its equipment-ness...
//oops! that retrieves a nullptr, because sword does not have a base item tag
ItemComponent *swordptr = sword.get_component<ItemComponent>(COMP_ITEM);
ItemComponent a = *swordptr; //dereferencing it crashes the program
}
}
Итак, как мне настроить и извлечь эти типы компонентов полиморфным способом?Я думаю, у меня мог бы быть большой список проверок if на теги в методе get_component, но на первый взгляд это кажется мне глупым решением.