Сравнение типов между производными классами

Я делаю движок для игры и не могу решить следующую проблему.

Итак, у меня есть базовый класс компонентов, из которого получены все различные компоненты. GameObject — это в основном контейнер для разных компонентов. Компоненты хранятся в векторе, содержащем указатели на базовый класс компонентов. Теперь мне нужно, чтобы класс GameObject имел шаблон функции-члена getComponent, который будет возвращать компонент с запрошенным типом из вектора.

Чтобы быть более понятным:

class Component
{
/..../
};

class RigidBody : Component
{
/..../
};

class Animation : Component
{
/..../
};

class GameObject
{
public:
template <class T>
T* getComponent();

void addComponent(Component*);
private:
std::vector<Component*> m_components;
};

/...../

GameObject test;
test.AddComponent(new RigidBody());
test.AddComponent(new Animation());
Animation * animation = test.getComponent<Animation>();

Или что-то в этом роде.

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

Так как указатели в векторе имеют базовый тип компонента, как я могу проверить, были ли они изначально запрошенного типа? Заранее спасибо!

-2

Решение

При условии, что Component имеет по крайней мере одну виртуальную функцию (иначе какой смысл наследовать от нее, верно?), вы должны иметь возможность делать то, что вам нужно, используя информацию о типе времени выполнения (RTTI) и dynamic_cast, как это:

template <class T> T* getFirstComponent() {
for (int i = 0 ; i != m_components.size() ; i++) {
T *candidate = dynamic_cast<T*>(m_components[i]);
if (candidate) {
return candidate;
}
}
return nullptr;
}

Напомним, что dynamic_cast<T*> вернет ненулевое значение только тогда, когда приведение выполнено успешно. Код выше проходит через все указатели и выбирает первый, для которого dynamic_cast<T*> преуспевает.

Важная заметка: Хотя это и должно заставить вашу программу делать то, что вы хотите, рассмотрите возможность изменения дизайна: вместо того, чтобы извлекать объекты по типу, предоставьте им виртуальные функции, которые позволят вам использовать их все единообразно. Бессмысленно класть объекты разных классов в один контейнер, только чтобы потом их раздвигать. RTTI следует использовать как последнее средство, а не как основной инструмент, потому что это делает вашу программу более трудной для понимания.

Другой допустимый подход — хранить отдельные компоненты отдельно, а не в одном векторе, и получать вектор только тогда, когда вам нужно обрабатывать объекты равномерно.

Менее важное примечание: если nullptr не компилируется в вашей системе, замените на return 0,

1

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


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