Reputation: 237
I have three classes, 2 of which rely on the functionality of each other, and one which contains pointers to and is included in both:
Player:
#pragma once
#include <SFML\Graphics.hpp>
#include "RenderableObject.h"
//#include "Renderer.h"
class Renderer;
class Player : public RenderableObject
{
public:
Player(int size, Renderer* renderer);
~Player();
void render();
void setX(int x);
void setY(int y);
int getX();
int getY();
void setVelX(float x);
void setVelY(float y);
float getVelx();
float getVely();
int getSize();
private:
int size;
int x;
int y;
float velx;
float vely;
Renderer* ren;
};
GameManager:
#pragma once
#include "Player.h"
class Renderer;
class GameManager
{
public:
GameManager(Renderer* r);
~GameManager();
Player* getBall();
private:
Player* ball;
};
Renderer:
#pragma once
#include <SFML\Graphics.hpp>
#include "GameManager.h"
#include "Player.h"
class Renderer
{
public:
Renderer(GameManager* game);
~Renderer();
sf::RenderWindow* getWindow();
void draw();
void renderCircle(int size, int x, int y);
void renderSquare(int size, int x, int y);
private:
sf::RenderWindow* win;
GameManager* game;
Player* ball;
};
I suspect there is some sort of circular dependency going on here. I managed to reduce the 60 odd errors down to 3, by adding "class Renderer;" to the Player header file. However, I'm now receiving "Use of undefined type" errors.
It might help to give a higher level view of what I want to achieve:
The GameManager object should hold an instance (maybe more) of player. This GameManager object is shared between subsystems such as Renderer so they all have access to the same resources.
The Renderer object should be able to call the Player object's (retrieved from the GameManager object) render() function, which in turn should call back to the Renderer object's renderCircle() object.
I'm hoping this is a simple case of re-arranging the includes, without having to re-design what I've already done.
Upvotes: 0
Views: 682
Reputation: 409166
In a header file, where you only declare variables that are pointers or references, all the compiler needs to know is that a class exists, nothing more. It doesn't need to know how big it it, or what members the class have. Therefore it's enough with a forward declaration.
However, in the source files where the variable is used, objects are created, and member functions are called, then the compiler need the full definition which means you have to include your whole header file.
Taking your code, simplified:
Player.h
#pragma once
class Renderer;
class Player
{
public:
Player(Renderer*);
private:
Renderer* ren;
};
GameManager.h
#pragma once
class Renderer;
class GameManager
{
public:
GameManager(Renderer*);
private:
Renderer* ren;
};
Renderer.h:
#pragma once
class Player;
class GameManager;
class Renderer
{
public:
Renderer(GameManager*);
private:
GameManager* game;
Player* ball;
};
The above header files are about the same that you already have, with the exception that I used forward declarations in Renderer.h
instead.
Now the Renderer.cpp
source file, where the Player
and GameManager
objects are actually created and used, we need the full definition from the header files:
#include "Renderer.h"
#include "Player.h"
#include "GameManager.h"
Renderer::Renderer(GameManager* game)
: game(game), ball(new Player)
{
}
// Other functions that calls member function in the `man` and `ball` objects
Of course, you need to #include "Renderer.h"
in the Player.cpp
and GameManager.cpp
source files.
If you have other errors, they are because of other things you done, not because of the circular dependencies, as those have been solved with the forward declarations.
Upvotes: 2