2013-09-21 4 views
1

Например немного Computergame с тремя классами игрока, Бота и игрыКак два класса на C++ могут видеть друг друга?

Игрок имеет метод, который проверяет, если игрок сталкивается с ботом

// Player.h 
#include Game.h 
#include Bot.h 

class Player { 
    private: 
    bool collision(Game g) { 

     for (Bot bot: g.bots) 
     ... 
    } 

}; 

Bot.h (простыми, причинно него имеет некоторые другие атрибуты, как фактическое положение и до сих пор)

// Bot.h 


class Bot { 
    public: 
    Bot() 
}; 

Gameclass обрабатывает Gameloop и список Боты

//Game.h 
#include Bot.h  
#include Player.h 

class Game { 

public: 
Player player: 
std::vector<Bot> bots 
void loop() { player.collision() } 

}; 

Итак, у нас есть проблема, что Game.h включает Player.h и наоборот.

Как я могу это решить?

+3

Почему player.h включает game.h? В коде, который вы опубликовали, нет причин. Если есть хорошая причина для player.h включить game.h, тогда нам нужно знать, что это такое, прежде чем мы сможем дать решение. – john

+0

Джон, ты прав, спасибо. Я исправил это. Цикл for должен быть в игровом классе, а не в игре. – user2796729

ответ

3

Хотя другие ответы здесь, безусловно, являются технически правильными, всякий раз, когда я сталкиваюсь с подобной ситуацией, я вижу это как указывающий на потенциальный недостаток в моем дизайне. Что у вас есть циклические зависимости, как так:

enter image description here

Это проблема не только для реализации, это означает, что существует слишком много coupling между классами, или, наоборот, слишком мало информации прячется. Это означает, что вы не можете создать Player, независимо от Game, например.

Так что, если возможно, я бы предпочел такую ​​ситуацию, когда Game, поскольку делегаты контроллера работают с другими классами.

enter image description here

Один из способов сделать это для Game передавать ссылки на свои собственные свойства, как и когда Player нуждается в них.

, например, иметь collision принимают параметр bots, а не `Игра

bool collision(const std::vector<Bot&> bots) { 
    // note pass objects by const ref is usu preferred in C++ to pass by value 

    for (Bot bot: g.bots) 
    ... 
} 

(примечание в более сложном подходе, он может передать интерфейсы, то есть абстрактные базовые классы, на себя).

Если все остальное не удастся, вы можете вернуться к использованию форвардного объявления.

+0

Отлично, спасибо за помощь и ваши диаграммы! Оно работает :) – user2796729

1

Я не думаю, что вы можете это сделать, поскольку если A содержит B, а B содержит A, это будет бесконечный размер. Infact вы можете создать два класса, которые хранят указатели друг с другом, используя опережающее объявление, так что два класса знают о существовании друг друга

2

В этом случае проще всего вещь будет объявлением вперед и перемещение некоторого кода из файла заголовка в исходный файл.

Как это

Player.h

#include "Bot.h" 

class Game; // forward declaration 

class Player { 
    private: 
    bool collision(Game g); 
}; 

Player.cpp

#include "Player.h" 
#include "Game.h" 

bool Player::collision(Game g) { 

    for (Bot bot: g.bots) 
    ... 
} 

форварду декларации сообщает компилятору, что Game является именем класса, но ничего другого. Поэтому метод Player::collision должен быть перемещен в файл Player.cpp, где доступно полное определение игры.

Смежные вопросы