Reputation: 8387
Classes in my application work like this: Creature
has few fields with Action
s. When these Action
s must be run Creature
calls someActionField->do(this)
. Action has method viod do(Creature* cr)
and all information about what to do with this Creature
.
So, Creature must have Action
field and know that Action
has do
method. Action must know that Creature
has such fields like: Will, HP, etc...
I've got
creature.h
#include "effect.h"
#include "heedupdate.h"
namespace Core
{
class Action;
class Creature : public NeedUpDate
{
public:
virtual ~Creature();
int HP;
Action onHit;
Action onDie;
// ...
};
}
#endif
And action.h
#include "creature.h"
namespace Core
{
class Action
{
public:
Action();
virtual void _do(Creature* cr);
virtual ~Action();
};
But in this case field `onDie' has incomplete type
error appears. If I include action.h into creature.h - I use files 'before each other'.
Upvotes: 4
Views: 2130
Reputation: 206831
You Creature
class has members of type Action
. The compiler needs to know the full definition of the Action
class to compile that - an incomplete type as produced with a forward declaration is not enough.
The Action
class only requires a pointer to a Creature
object in that header. In that case, the compiler only needs to know that Creature
will be defined at some point.
In your specific case, you could get away with inverting the order in which you declare your classes.
(i.e. forward-declare Creature
in action.h
, and include action.h
in creature.h
)
Upvotes: 8
Reputation: 206566
When you forward declare a type, all the compiler know is that this type exists; it knows nothing about its size, members, or methods, hence it is called an Incomplete Type
You cannot use an incomplete type to declare a member(because compile needs to know the size of the type while declaring it) and hence you get the error.
You don't need to #include "creature.h" in action.h but you just need to forward declare class Creature. You do need to #include "action.h" in creature.h
Your header files should have the following construct:
creature.h
#include "effect.h"
#include "action.h"
#include "heedupdate.h"
action.h
class creature;
This makes use of two rules:
action.h
only declares a function which accepts an Incomplete type(Creature)
creature.h
has to include action.h
because it declares a member of type Action
.
Upvotes: 3
Reputation: 64253
Use references, or pointers :
#include "effect.h"
#include "heedupdate.h"
namespace Core
{
class Action;
class Creature : public NeedUpDate
{
public:
virtual ~Creature();
int HP;
Action & onHit;
Action & onDie;
// ...
};
}
#endif
This way you can break dependencies and not need a fully declared Action
class
Upvotes: 0
Reputation: 33126
You don't need to #include "creature.h" in action.h. All you need is a forward declaration of class Creature. You do need to #include "action.h" in creature.h because onHit and onDie are instances of Action.
Upvotes: 2
Reputation: 96266
in action.h put class Creature;
and in the other one #include "action.h"
For pointers you don't need complete definition because it's just a pointer and the compiler can generate "code" for it. If you use a simple class/struct the compiler has to have knowledge of the type because it needs to know how big it is.
Upvotes: 3