Cross-References C++

Started by
3 comments, last by JasonBlochowiak 17 years, 8 months ago
In my simple TicTacToe game I have one class for the game state and one class for the player. The player has to access the game state, so I pass a reference in the constructor. The GameState Class on the other hand has to have a reference to the player to notify when it's the players turn. First the code I have at the moment doesn't work. The compiler is complaining about cross-references (I believe). Second I don't even know it this design is a good idea. I thought about introducting a third class StateManager, but this seems to be not a very good solution. In Java the problem can be solved with an interface observable and observer.
[source="cpp"]
// Player.h
#include "GameState.h"
#ifndef PLAYER_H
#define PLAYER_H

class Player  {
public:
	Player(GameState*state);
	~Player();
	void move();
protected: 	
	GameState *m_state;

};
#endif // PLAYER_H 

// GameState.h
#ifndef GAMESTATE_H
#define GAMESTATE_H

#include "Player.h"

class GameState {
public:
	GameState();
	~GameState();
	// make a move , return false if the move is not possible
	bool movePossible(int pos, int type);
	void makeMove(int pos, int type);
	
	int* getBoard();
	void AI_move();
	bool test_game_over();
	
private:
	int* m_board;
	int users_turn;
	int move_number;
	Player *AI;

};

#endif // GAMESTATE_H

BTW: I thought about opening a journal to collect all my questions (I have many). Is that a good idea?
Advertisement
Read this.
First, if the compiler is generating errors, it is extrememly difficult to help you solve the errors without knowing exactly what the errors are. Saying "The compiler is complaining about cross-references (I believe)" is not useful. Though in this case, it is pretty easy to guess what the problem is just by looking at the code.

Second, there is a problem with the design (though it is partially a matter of opinion). The state of a game like TTT is independent of the players. Your game state should not include players. That means that you need another class that controls the game. It knows about the players, the game state, and the game. It could be implemented something like this:
    GameState    gamestate;    while ( !gamestate.GameIsOver() )    {        gamestate.Display();        if ( gamestate.WhoseTurn() == X )        {            players[X]->Move( &gamestate );        }        else        {            players[O]->Move( &gamestate );        }    }    gamestate.Display();    if ( gamestate.GetWinner() == DRAW )    {        cout << "The game is a draw." << endl;    }    else    {        cout << "The winner is " << gamestate.GetWinner() << endl;    } 
John BoltonLocomotive Games (THQ)Current Project: Destroy All Humans (Wii). IN STORES NOW!
One problem with your code is as follows:
If a source file includes Gamestate.h first, the preoprocessor will get to the line which says #include "Player.h".
At this point it will start on player.h, but when it gets to the first include of this , Gamestate.h, it will go into this header file but get no further because of the #ifndef statement. This is good, it prevents an endless loop.

However, when the compiler leaves the #include "Gamestate.h" statement it continues to compile the Player.h header file, but the line highlighted below:

class GameState {
public:

private:

Player *AI;

};

is a pointer to a completely undefined type due to the order the header files were processed.

A simple way round this is to put forward declarators at the top of each header file like this:

in GameState.h
class Player;
class GameState {
....

in Player.h
class GameState;
class Player{
....


This just lets the compiler know that these classes will be defined later.
Quote:Original post by beany_boz
A simple way round this is to put forward declarators at the top of each header file like this:

in GameState.h
class Player;
class GameState {
....

in Player.h
class GameState;
class Player{
....


This just lets the compiler know that these classes will be defined later.


That's a good suggestion, but it's better to use something like Player_defs.h where you just define the classes. That way, if it's not a class, or there's some modifier for it, or it's a class that's declared using some utility macro, it's just in one place - the Player_defs.h file, rather than scattered throughout any headers that make reference to the class. Player.h should then also make use of Player_defs.h.

This topic is closed to new replies.

Advertisement