В настоящее время я занимаюсь разработкой RPG-игры на C ++, и я решил включить события на карту.
Я хотел, чтобы событие на карте вылечило игрока. Я решил, что самый простой способ сделать это — передать указатель на объект события из игры, используя ключевое слово this. Когда я занялся этим, была целая куча ошибок компилятора, которые, по-видимому, возникли в результате попытки включить класс, который в настоящее время пытается включить другой класс. (бесконечный цикл, я думаю?)
Например. У меня есть свой класс игры, и у него есть открытый член, принадлежащий классу mapManager. Затем объект ‘mapManager’ имеет объект ‘event’ в качестве члена. Объект ‘game’ также имеет объект ‘player’ внутри своих ‘членов. Мне нужно иметь переменные объекта «событие», которые есть у «игрока». Я мог бы честно бросать указатели всякий раз, когда они мне нужны, но это может стать громоздким.
Я пытаюсь спросить, есть ли простой способ, чтобы дочерний элемент родительского элемента имел доступ к другому дочернему элементу этого родительского элемента, или было бы проще просто указывать указатели на все дочерние классы, где они должны указывать на других дочерних элементов. ,
Вау … это имело очень мало смысла, но, надеюсь, кто-то сможет понять достаточно, чтобы дать мне хороший ответ. Вот некоторый код на случай, если это поможет.
:game.h
include "player.h"include "event.h"
class game
{
public:
player Player;
event Event;
};
:player.h
class player
{
public:
game* Game;
};
:event.h
class event
{
public:
game* Game;
};
Из-за этого «игра не называет тип», поэтому я попытался включить игру в event.h и player.h и получил ту же ошибку. Я хочу получить доступ к переменной HP игрока изнутри события.
Желательно избегать циклических ссылок, где это возможно; Однако если вы действительно Если вы хотите сделать это, то решение состоит в том, чтобы объявить ваш класс вперед. Game
в верхней части заголовочных файлов, которые будут использовать ссылки / указатели на него. например
#ifndef EVENTH
#define EVENTH
class Game;
class Event
{
Game* game;
};
#endif
а также..
#ifndef PLAYERH
#define PLAYERH
class Game;
class Player
{
Game* game;
};
#endif
Для заголовочных файлов, которые не нуждаются в знании реализации / размера Game
class, простого forward-объявления достаточно, чтобы сообщить компилятору о существовании класса с таким именем.
В вашем .cpp
исходные файлы (где реализация Game
на самом деле важно и используется реализацией Player / Event) вам все еще нужно #include
заголовок, содержащий определение вашего класса Game.
//game.h
class event;
class game {
event _e;
private:
game(){}
//game& operator=(game& other) {}
~game(){}
public:
static game & getInstance() {
static game instance;
return instance;
}
event& getEvent() {return _e;}
};//HealEventObserver.h
class HealEventObserver {
public:
virtual void heal() = 0;
virtual ~HealEventObserver(){}
};
//player.h include game.h and HealEventObserver.h event.h
class Player : public HealEventObserver
{
public:
virtual void heal() {/*heal the player*/}
Player() {
game& instance = game::getInstance();
event& e = instance.getEvent();
e.registerObserver(this);
}
};
//event.h include HealEventObserver.h
class event {
std::set<HealEventObserver*> _observers;
void notify() {
std::set<HealEventObserver*>::iterator it = _observers.begin();
std::set<HealEventObserver*>::iterator end = _observers.end();
for( ;it!=end; ++it) {
it->heal();
}
}
public:
void registerObserver(HealEventObserver* observer) {_observers.insert(observer);}
};
Не заставляйте ваш объект события вообще менять игрока, просто заставьте событие сказать игроку, чтобы он исцелил себя. Также, если игра должна представлять все, сделайте ее глобальной.
Ответить на комментарий: (Это только мое мнение и больше ничего.)
После небольшого исследования я нашел эту ссылку, которая дает имена замечательных ссылок.