This question already has an answer here:
Implementing the Component pattern in C++, I came upon a problem related with includes.
I have an Entity
class, which has the following components: Renderer
, Physics
and Collider
. They inherit from Component
, which has a single virtual method Component->update(elapsedTime)
and a reference to the Entity
it belongs to.
Each time an Entity
is updated, its components are updated too. As the components alter the Entity
's state, I thought it would be a good idea making them have a reference to the Entity
they belong too (I could pass the Entity
as a parameter in the Component->update()
call but for performance I prefer not doing so).
Now I must include Renderer
, Physics
and Collider
from Entity
, and include Entity
from Component
. Luckily, Entity
calls methods from the above but Component
just stores a reference to Entity
, so I should include normally Renderer
, Physics
and Collider
from Entity
, and forward declare Entity
from Component
. After doing so, I found a problem which I cannot solve or know how to investigate. So I tried the other way around, and other problems risen up.
- Including normally
Renderer
,Physics
andCollider
fromEntity
, and forward declareEntity
fromComponent
:
A class which includes Entity
would complain saying that Entity
is ambiguous. This is due to (I think) that class loading Entity
, then loading its Component
s which forward declare Entity
. How can I forward declare Entity
without having other classes complaining about this ambiguity?
- Including normally
Entity
fromComponent
, and forward declaringRenderer
,Physics
andCollider
fromEntity
:
In my Entity->update()
method I do this->collision->update()
which breaks, by saying that pointer to incomplete class is not allowed
.
How can I solve this without changing my class structure or behavior?
Here are the files, using the first example (including the components and forward declaring Entity
from Component
:
Entity.h
#ifndef ENTITY_H
#define ENTITY_H
#include "Collision.h"
#include "Physics.h"
#include "Renderer.h"
#include "TextureRenderer.h"
using namespace Components;
namespace Entities
{
class Entity
{
public:
Entity();
Collision* getCollision();
virtual void update(float elapsedTime);
protected:
Collision* collision;
Physics* physics;
Renderer* renderer;
};
}
#endif
Entity.cpp
#include "Entity.h"
namespace Entities
{
Entity::Entity()
{
}
Collision* Entity::getCollision()
{
return this->collision;
}
void Entity::update(float elapsedTime)
{
collision->update(elapsedTime);
physics->update(elapsedTime);
renderer->update(elapsedTime);
}
}
Component.h
#ifndef COMPONENT_H
#define COMPONENT_H
namespace Components
{
class Component
{
public:
Component(Entity* entity);
virtual void update(float elapsedTime) = 0;
protected:
Entity* entity;
private:
friend class Entity;
};
}
#endif
Component.cpp
#include "Component.h"
#include "Entity.h"
namespace Components
{
Component::Component(Entity* entity)
{
this->entity = entity;
}
}
Collision.h
#ifndef COLLISION_H
#define COLLISION_H
#include "Component.h"
namespace Components
{
class Collision : public Component
{
public:
void collide(Entity* entity);
protected:
virtual bool collidesWith(Entity* entity) = 0;
};
}
#endif
Collision.cpp
#include "Collision.h"
namespace Components
{
void Collision::collide(Entity* entity)
{
if (this->collidesWith(entity))
{
...
}
}
}
Renderer.h
#ifndef RENDERER_H
#define RENDERER_H
#include "Component.h"
namespace Components
{
class Renderer : public Component
{
public:
Renderer(Entity* entity);
virtual void update(float elapsedTime) override;
};
}
#endif
Renderer.cpp
#include "Renderer.h"
namespace Components
{
Renderer::Renderer(Entity* entity) : Component(entity){ }
void Renderer::update(float elapsedTime){}
}
And Physics
is pretty much empty and I don't feel like adding it right now.
Thanks a lot
I'm having way to much problems with includes. My code does a lot of double referencing for performance reasons, and each pair of classes accesses the methods of each other. C++ hates this, and defining which class should forward declare the other is a pain in the ass.
Aucun commentaire:
Enregistrer un commentaire