Как получить производный класс от интерфейса?

Пытаясь создать Entity-Component-System на C ++, я столкнулся с некоторыми проблемами, связанными с незнанием языка.

С классом Entity, который содержит интерфейс IComponent (который больше похож на флаг, говорящий «Я храню данные»), у меня есть метод Add , который добавляет компонент к сущности, если в нем уже нет другого IComponent того же класса.

Вот упрощенный пример кода:

struct IComponent{};

struct Foo : IComponent{ int x;};
struct Bar : IComponent{ int y; };

class Entity{
    vector<IComponent*> entityComponents;

    void Add(IComponent* componentToAdd){
        if("entityComponents" does not contain the class of "componentToAdd")
            entityComponents.add (componentToAdd)

    }
}

Мой ожидаемый результат был бы

Entity e;
Foo f;
Bar b;
Foo anotherF;

e.Add(f); // Works
e.Add(b); // Works
e.Add(anotherF); // Does not work because another 
                 //item in the array already inherits Foo

Но я не знаю, как получить базовый класс Foo и Bar из списка IComponents и проверить, повторяются ли они.

Как я могу их получить? Как я могу преобразовать IComponent в Foo, если Foo находится в списке IComponent?


person SeoFernando    schedule 24.06.2019    source источник
comment
vector<IComponent> Вы, вероятно, этого не хотите, но vector<IComponent*>. См. Также: Нарезка объектов   -  person Igor Tandetnik    schedule 24.06.2019
comment
Что вы собираетесь делать со всеми этими IComponent экземплярами? Помимо Add, как вы планируете их использовать?   -  person Igor Tandetnik    schedule 24.06.2019
comment
@IgorTandetnik Моя беда, починил. Я планирую получить их и изменить данные внутри них. С такими вещами, как GetComponent ‹Foo› (), HasComponent ‹Bar› (), RemoveComponent ‹Foo› () ...   -  person SeoFernando    schedule 24.06.2019
comment
Итак, как вы планируете реализовать, скажем, HasComponent<Bar>? Как только вы это узнаете, вы также узнаете, как предотвратить дублирование в Add.   -  person Igor Tandetnik    schedule 24.06.2019
comment
Проверяя, находится ли класс Bar в списке IComponent *, и они возвращают true, но я не знаю, как это сделать. Боюсь, мой вопрос может дублироваться.   -  person SeoFernando    schedule 24.06.2019


Ответы (2)


Оформить заказ dynamic_cast. Вы можете попытаться привести указатель на базовый класс к указателю на производный класс. Это не удается, если созданный объект не относится к производному типу и в этом случае возвращает значение null.

person Bar Stool    schedule 24.06.2019

Как указано в Барном стуле, моим решением было

template<typename T>
bool HasComponent(){
  for(Component* component: this->components)
        if(T* casted = dynamic_cast<T*>(component))
                return true;           
  return false;

}

А позже просто проверьте, ложно ли "HasComponent ()", а затем добавьте его.

person SeoFernando    schedule 24.06.2019
comment
Двойной if немного сбивает с толку. : S Результат сохранять не нужно :) Попробуйте: if (dynamic_cast<T*>(component)) return true; - person Bar Stool; 25.06.2019