Как правильно организовать взаимодействия объектов в игре, что бы не нужно было узнавать тип объекта(с++, ООП)?

У меня есть класс LevelLoader. Он возвращает вектор объектов BaseObject
Я передаю его в GameField.

Игрок побеждает, тогда, когда в GameField не остается ни одной Point.
Но как мне это определять?

Первое что приходит в голово - при добавлении объектов в GameField, проверяем, если добавляем Point, то увеличиваем pointsCount на 1 (с уменьшением при удалении Point проблем нет).

Но проверять тип объектов - это очень не хорошо. Поэтому нужно как-то по-другому.

Может быть лучше считать количество созданных точек в LevelLoader и передавать в GameField? Но это тоже не кажется лучшим решением.

p.s. ну и static поле в Point - тоже не вариант в принципе, так как меня интересует количество точек в GameField, а не вообще (хоть в практически всегда оно и будет совпадать).
  • Вопрос задан
  • 95 просмотров
Пригласить эксперта
Ответы на вопрос 1
@d0lph1n
Не вижу красивого решения, подходящего под Ваши ограничения. Мне кажется, можно добавить дополнительную абстракцию: BaseObject <- BasePoint <- Point, а в GameField из LevelLoader передавать не массив BaseObject'ов, а контейнер (назовем его Level, например), который содержит Ваши точки и прочие игровые объекты в отдельных структурах данных.

С другой стороны, если у Вас GameField - это доска для игры в ГО, на которой всего-то и есть, что черные точки да белые точки, тогда вовсе нет смысла создавать BaseObject. Задача больше похожа на архитектурную, чем на техническую, и решать ее будет удобнее, если Вы подробнее опишете задумку.

UPD. p. s. От "грязных" трюков совсем уж отказываться не стоит, особенно если приперло. В Qt, например, реализован механизм определения типа, и это не костыль, а жизненно важная фича для реализации концепции управления объектами. А в Java так и вовсе существует т. н. "рефлексия", что подразумевает не только способ определить имя класса, но и получить информацию о его методах и атрибутах. Казалось бы, какая гадость! Но ведь работает.

UPD2: Не знаю, актуально это еще для Вас или нет, но я наткнулся вот на какой трюк в Книге "Эккель - Философия C++, часть вторая", страница 234.

template <class t>
class base {
    static int sn_objects;
public:
    base() {
        sn_objects++;
    }
    ~base() {
        sn_objects--;
    }
    static int count() {
        return sn_objects;
    }
};

template<class t> int base<t>::sn_objects = 0;

class daughter : public base<daughter> {};
class son : public base<son> {};

int main(int argc, char** argv) {
    daughter d1;
    daughter d2;
    daughter d3;
    son s1;
    std::cout << daughter::count() << std::endl; // --------- 3 ---------
    std::cout << son::count() << std::endl; <b>   // --------- 1 ---------

    return 0;
}


Однако в этом случае мы не сможем посчитать все объекты, унаследованные от base. Только если мы base унаследуем от какого-нибудь другого класса, где будем считать статические переменные по-старинке:

#include <iostream>

class the_very_base {
    static int sn_common_counter;
public:
    the_very_base() {
        sn_common_counter++;
    }
    ~the_very_base() {
        sn_common_counter--;
    }
    static int count_all() {
        return sn_common_counter;
    }
};
int the_very_base::sn_common_counter = 0;

template <class t>
class base : public the_very_base {
    static int sn_objects;
public:
    base() {
        sn_objects++;
    }
    ~base() {
        sn_objects--;
    }
    static int count() {
        return sn_objects;
    }
};

template<class t> int base<t>::sn_objects = 0;

class daughter : public base<daughter> {};
class son : public base<son> {};

int main(int argc, char** argv) {
    daughter d1;
    daughter d2;
    daughter d3;
    son s1;
    std::cout << daughter::count() << std::endl;              // --------- 3 ---------
    std::cout << son::count() << std::endl;                       // --------- 1 ---------
    std::cout << the_very_base::count_all() << std::endl; // --------- 4 ---------

    return 0;
}


Основано, разумеется, на статических переменных, но только в самом исходном коде статическая переменная всего одна - не приходится объявлять их по 10 штук.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы