Circular dependency

The Partridge Family were neither partridges nor a family. Discuss.
egizz983
Posts: 311
Joined: August 27th, 2016, 12:30 pm

Circular dependency

Post by egizz983 » October 27th, 2016, 11:46 am

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)

albinopapa
Posts: 4373
Joined: February 28th, 2013, 3:23 am
Location: Oklahoma, United States

Re: Circular dependency

Post by albinopapa » October 27th, 2016, 1:53 pm

PlayerSprite.h includes StateStand.h, StateStand.h includes PlayerState.h, PlayerState.h includes PlayerSprite.h...
If you think paging some data from disk into RAM is slow, try paging it into a simian cerebrum over a pair of optical nerves. - gameprogrammingpatterns.com

albinopapa
Posts: 4373
Joined: February 28th, 2013, 3:23 am
Location: Oklahoma, United States

Re: Circular dependency

Post by albinopapa » October 27th, 2016, 2:00 pm

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.
If you think paging some data from disk into RAM is slow, try paging it into a simian cerebrum over a pair of optical nerves. - gameprogrammingpatterns.com

reductor
Posts: 49
Joined: October 24th, 2016, 12:23 pm

Re: Circular dependency

Post by reductor » October 27th, 2016, 2:01 pm

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)

egizz983
Posts: 311
Joined: August 27th, 2016, 12:30 pm

Re: Circular dependency

Post by egizz983 » October 27th, 2016, 2:07 pm

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

egizz983
Posts: 311
Joined: August 27th, 2016, 12:30 pm

Re: Circular dependency

Post by egizz983 » October 27th, 2016, 2:37 pm

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

albinopapa
Posts: 4373
Joined: February 28th, 2013, 3:23 am
Location: Oklahoma, United States

Re: Circular dependency

Post by albinopapa » October 27th, 2016, 3:01 pm

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.
If you think paging some data from disk into RAM is slow, try paging it into a simian cerebrum over a pair of optical nerves. - gameprogrammingpatterns.com

albinopapa
Posts: 4373
Joined: February 28th, 2013, 3:23 am
Location: Oklahoma, United States

Re: Circular dependency

Post by albinopapa » October 27th, 2016, 3:05 pm

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.
If you think paging some data from disk into RAM is slow, try paging it into a simian cerebrum over a pair of optical nerves. - gameprogrammingpatterns.com

User avatar
chili
Site Admin
Posts: 3948
Joined: December 31st, 2011, 4:53 pm
Location: Japan
Contact:

Re: Circular dependency

Post by chili » October 28th, 2016, 2:08 am

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.
Chili

egizz983
Posts: 311
Joined: August 27th, 2016, 12:30 pm

Re: Circular dependency

Post by egizz983 » October 28th, 2016, 9:26 am

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

Post Reply