У меня есть иерархия игровых объектов:
class GameObject {
public:
virtual void update(float dt) = 0;
virtual void draw() = 0;
};
class Building : public GameObject {}
class Sawmill : public Building {}
class Human : public GameObject {}
и так далее. Все объекты управляются игрой (которая не является подклассом GameObject :). Игра сохраняет все объекты в std :: vector и успешно вызывает виртуальные методы, такие как update и draw, и это все хорошо. Но иногда мне нужно определить, с каким типом GameObject я имею дело. Для этого случая мы придумали решение: GameObject имеет перечисление типов GameObject, и каждый подкласс GameObject возвращает свое собственное значение из этого перечисления.
class GameObject {
public:
enum GOType
{
GOGameObject,
GOBuilding,
GOSawmill,
GOHuman,
...
}
static GOType Type() { return GOGameObject; }
virtual GOType getType() const { return GameObject::Type(); }
};
class Building : public GameObject {
public:
static GOType Type() { return GOBuilding; }
virtual GOType getType() const { return Building::Type(); }
};
Итак, у каждого подкласса GameObject есть своя собственная версия метода «static GOType Type ()», которая возвращает значение из enum GOType. И он перегружен виртуальным методом «GOType getType () const», который просто вызывает собственный метод класса Type (). В любом месте игры я могу проверить, является ли объект, на который у меня есть указатель, например, зданием:
if (obj && obj->getType() == Building::Type()) {
// then do stuff
}
Чтобы прояснить ситуацию - это решение отлично работает и зарекомендовало себя как расширяемое и очень эффективное (первое решение, которое мы придумали, это возвращение строк в getType () и сравнение их; это было очень медленно).
Единственный недостаток, который я вижу, это то, что мне приходится расширять GOType в GameObject каждый раз, когда я добавляю новый подкласс GameObject. Теперь он содержит около сотни типов, и он не выглядит и не чувствует себя прекрасно (я здесь перфекционист:)
Итак, мой вопрос: есть ли другое решение проблемы, столь же эффективное, как это, но без необходимости расширения GOType в GameObject?