Page 1 of 2

Circular dependency

Posted: October 27th, 2016, 11:46 am
by egizz983
Guys i fucked up somewhere with a circular dependency and could not find anywhere i re code whole my project and then this happens .
GitHub:https://github.com/egizz983/C--

So what i did i just re code everything but i believe problem is inside states classes and playersprite class .

PlayerState.h

Code: Select all

#include "PlayerSprite.h"
StateFall,StateJump,StateStand,StateRun.h

Code: Select all

#include "PlayerState.h"
PlayerSprite.h

Code: Select all

#include "StateStand.h"
before i made a changes with a states its used to work , now i just got tons of errors witch makes no sense (same problem when i had circular dependency last time)

Re: Circular dependency

Posted: October 27th, 2016, 1:53 pm
by albinopapa
PlayerSprite.h includes StateStand.h, StateStand.h includes PlayerState.h, PlayerState.h includes PlayerSprite.h...

Re: Circular dependency

Posted: October 27th, 2016, 2:00 pm
by albinopapa
This is why you should not use the header file to write all your code. Take StateStand.h out of PlayerSprite.h. Forward declare PlayerState in PlayerSprite.h and include StateStand.h in the PlayerSprite.cpp file. Move definitions, at least the PlayerSprite constructor, to the cpp file.

Re: Circular dependency

Posted: October 27th, 2016, 2:01 pm
by reductor
What are the error message(s)? If your using include guards or "pragma once" then your includes are less of an issue then what they contain. You should also rely on forward declarations where you can get away with incomplete types.

For debugging these sort of issues, I suggest finding individual files that fail to compile and build them on their own this reduces noise from parallel builds. (In MSVC solution view you can right click a file and select compile)

Re: Circular dependency

Posted: October 27th, 2016, 2:07 pm
by egizz983
albinopapa wrote:This is why you should not use the header file to write all your code. Take StateStand.h out of PlayerSprite.h. Forward declare PlayerState in PlayerSprite.h and include StateStand.h in the PlayerSprite.cpp file. Move definitions, at least the PlayerSprite constructor, to the cpp file.
Yea i was thinking about this just was not sure because i was believing that pragma once solve this problem i was believing like i cant include State inside sprite and sprite inside state , i was hoping i can do the way i did above ,and now i see a benefit of making a cpp and header file , and if i make PlayerSprice.cpp file i would not even need forward declaration .
reductor wrote:What are the error message(s)? If your using include guards or "pragma once" then your includes are less of an issue then what they contain. You should also rely on forward declarations where you can get away with incomplete types.

For debugging these sort of issues, I suggest finding individual files that fail to compile and build them on their own this reduces noise from parallel builds. (In MSVC solution view you can right click a file and select compile)
error messages witch makes no sense at all like missing ; , Undeclared , UNdefined and so on 129 erros , and based on my experience i know that this because of circular dependency

Re: Circular dependency

Posted: October 27th, 2016, 2:37 pm
by egizz983
Okay so i got another problem now :
PlayerControl.h :

Code: Select all

#pragma once
#include "ChiliWin.h"
#include "Keyboard.h"
#include "PlayerDirection.h"

class PlayerSprite;

class PlayerControls {
public:
	PlayerControls(PlayerSprite* player)
		:
		pPlayer(player)
	{}
	void CheckControls(Keyboard& kbd);
private:
	PlayerSprite* pPlayer;
};
PlayerControl.cpp

Code: Select all

#include "PlayerControls.h"
#include "PlayerSprite.h"

void PlayerControls::CheckControls(Keyboard& kbd)
{
	Keyboard::Event kevent = kbd.ReadKey();
	switch (kevent.GetCode())
	{
		case VK_LEFT:
			pPlayer->GetDirection()->SetLeft();
			pPlayer->GetPlayerState()->KeyLeft(kevent.KeyState());
			break;
		case VK_RIGHT:
			pPlayer->GetDirection()->SetRight();
			pPlayer->GetPlayerState()->KeyRight(kevent.KeyState());
			break;
		case VK_SPACE:
			pPlayer->GetPlayerState()->KeySpace(kevent.KeyState());
			break;
	}
}

PlayerSprite.h

Code: Select all

#pragma once
#include "Keyboard.h"
#include "PlayerControls.h"
#include "LoadPlayerRes.h"

class PlayerState;

class PlayerSprite{
public:
	PlayerSprite(float x, float y, float speed);
	~PlayerSprite() {
		delete pCurrentState;
	}
	void Draw(Graphics& gfx) const;
	void Update(Keyboard& kbd);
	float GetX() const { return x; }
	float GetY() const { return y; }
	float GetSpeed() const { return speed; }
	void SetX(float newx) { x = newx; }
	void SetY(float newy) { y = newy; }
	void SetSpeed(float newspd) { speed = newspd; }
	void SetState(PlayerState* state) { pCurrentState = state; }
	SurfaceAnimation* GetSurface(std::string name) { 
		return res.GetSurface(name);
	}
	PlayerState* GetPlayerState();
	PlayerDirection* GetDirection();
private:
	float x, y, speed;
	LoadPlayerRes res;
	PlayerDirection PlayerDirection;
	PlayerControls* PlayerControl;
	PlayerState* pCurrentState;
};
So not problem is that PlayerControl.cpp gives me errors on those lines

Code: Select all

pPlayer->GetPlayerState()->KeyLeft(kevent.KeyState());
pPlayer->GetPlayerState()->KeyRight(kevent.KeyState());
pPlayer->GetPlayerState()->KeySpace(kevent.KeyState());
its because of incomplete class of PlayerState , any way around ?
i mean if i do as i did before i would have to include PlayerSprite in each State class and then include PlayerState inside a PlayerSprite , and now i only do include to main class

Re: Circular dependency

Posted: October 27th, 2016, 3:01 pm
by albinopapa
In PlayerControls.cpp, you should #include PlayerState.h.

Incomplete types means the compiler knows about the type, but doesn't know how it's implemented, basically.

Re: Circular dependency

Posted: October 27th, 2016, 3:05 pm
by albinopapa
reductor wrote:What are the error message(s)? If your using include guards or "pragma once" then your includes are less of an issue then what they contain. You should also rely on forward declarations where you can get away with incomplete types.

For debugging these sort of issues, I suggest finding individual files that fail to compile and build them on their own this reduces noise from parallel builds. (In MSVC solution view you can right click a file and select compile)
Not sure what you mean here. The include guards, #ifndef blabla #define blabla #endif and #pragma once do prevent the files form being included more than once, but it is still possible to have a ton of compilation errors if you include A.h in B.h and include B.h in A.h. Worst of all, the errors are really erroneous and make it seem like you forgot a semi-colon or are missing some #include somewhere.

Re: Circular dependency

Posted: October 28th, 2016, 2:08 am
by chili
Yup. A includes B, B tries to include A but is blocked by the guard, and then the references to A in B are undefined and errors are flagged. Can only be solved by forward declaration (typically by splitting up the definition and the implementation into separate files). Unless you want to use a more complicated design pattern that eliminates the circular dependency.

Re: Circular dependency

Posted: October 28th, 2016, 9:26 am
by egizz983
Yea everything are set now i think this is much better then was before i also change almost everything its because similar to what you was coding in a tutorial but now i think that this is a good this to do , i made some changes or improvements witch will help me a lot in future or at least its looks better :D I made a new function inside a Keyboard.h witch instead of checking if it was pressed or if it was released or if its was invalid will return me an event that was made , i know i will need an include to know that enum type but i dont think that is problem :

Code: Select all

Type KeyState(){
			return type;
		}
and then i switch keystate inside a state machine to know what to do i think its looks sexy now :D
https://github.com/egizz983/C--/
before i update GitHub i group everything into folder so i dont think that it would work like this unleass i would play with includes