I’m picking up C++ again after a while, and I’m having trouble understanding a certain behavior. I don’t know if it’s a fault in VS 2010, or just C++. I’m working on a school project, so forgive the “hokey-ness” of the program. First, I’ll just post the relevant files and their contents:
BarFly.h:
#ifndef PJ_BARFLY_H
#define PJ_BARFLY_H
#include "BarFlyOwnedStates.h"
#include "BaseGameEntity.h"
#include "FSM\StateMachine.h"
class BarFly : public BaseGameEntity {
private:
StateMachine<BarFly>* state_machine;
public:
BarFly(int id);
};
#endif // PJ_BARFLY_H
BarFlyOwnedStates.h:
#ifndef PJ_BARFLYOWNEDSTATES_H
#define PJ_BARFLYOWNEDSTATES_H
#include "BarFly.h"
#include "FSM/State.h"
class BarFly; // << Line A <<
class CarousingState : public State<BarFly>
{
public:
static CarousingState *Instance();
// Some non-relevant functions
};
#endif // PJ_BARFLYOWNEDSTATES_H
BarFly.cpp:
#include "BarFly.h"
BarFly::BarFly(int id) : BaseGameEntity(id) {
state_machine = new StateMachine<BarFly>(this);
state_machine->SetCurrentState(CarousingState::Instance()); // << Line B <<
}
Alright, so my question is, why do I need to include Line A? When I leave that out, VS complains about Line B, saying that it doesn’t recognize CarousingState* as a State<BarFly>*.
Any feedback is appreciated.
The problem is that you have a circular header dependency;
"BarFly.h"and"BarFlyOwnedStates.h"each try to include each other. The result is that, when you include"BarFly.h", the include guards mean that the definition ofBarFlycomes after that ofCarousingState, soBarFlyhas not been declared at the point it’s used as a template argument.Line A is a “forward declaration” (or just “declaration”); it declares that the class exists, but does not define the class. Until the class is defined, it’s known as an “incomplete type”, and can be used in some situations.
In general, you should avoid circular dependencies like this, as they can cause much confusion. Include a header only when you actually need to, and just use forward declarations of classes whenever you can.
In this case, it looks like you can remove
#include "BarFlyOwnedStates.h"fromBarFly.h, and depending on whatStatedoes with its template argument, you might also be able to remove#include "BarFly.h"fromBarFlyOwnedStates.h(keeping the forward declaration on Line A). You will need to include both headers from the source file.