In a Game class function I am allocating a Boundary class to the stack
void Game::loadContent()
{
Boundary b(this, body);
}
The boundary class has a pointer to the main Game class and a pointer to a rigid body. I'm not certain whether I should use a reference for each though? Some clarity here would be helpful for reasons explained later.
class Boundary : public DynamicEntity
{
public:
Boundary(Game *game, btRigidBody *body);
~Boundary(void);
// Override functions
virtual void draw(float dt);
virtual glm::vec3 getPosition();
virtual void update(float dt);
};
The DynamicEntity class assigns the body and handles the pointer deletion in its destructor.
class DynamicEntity : public Entity
{
public:
virtual ~DynamicEntity(void);
virtual void draw(float dt) = 0;
btRigidBody* getBody();
glm::vec3 getPosition() = 0;
virtual void update(float dt) = 0;
protected:
explicit DynamicEntity(Game *game, btRigidBody *body);
btRigidBody *m_body;
};
DynamicEntity.cpp Destructor
DynamicEntity::~DynamicEntity(void)
{
m_game->m_dynamicsWorld->removeRigidBody(m_body);
delete m_body;
}
The DynamicEntity derives from the base class of all game objects called Entity
Entity.h
class Entity
{
public:
// Make destructor virtual as this is a base class
virtual ~Entity(void);
virtual void draw(float dt) = 0;
int getID();
virtual glm::vec3 getPosition() = 0;
virtual void update(float dt) = 0;
protected:
explicit Entity(Game *game); // Abstract base constructor
Game *m_game;
int m_id; // Unique ID
};
I can't call delete on the Game class pointer in this class' destructor though which is why I am not sure whether passing as a pointer is the correct method (instead of a reference)?
Entity::~Entity(void)
{
// Derived class destructors are called first
delete m_game; // ERROR
}
The Entity class adds a pointer to itself which can be accessed via a list in the Game class (useful for iterating and calling Entity functions in the main Game class).
Entity::Entity(Game *game)
: m_game(game), // Initialise members
m_id(m_game->g_idGenerator->generateNewID()) // Generate unique ID
{
m_game->m_entities.push_back(std::shared_ptr<Entity>(this));
}
The main problem I am having is that once the Game::loadContent() method has finished the destructor is called for the Entity class. This ruins the *shared_ptr* stored in the list and errors occur when trying to call any of the virtual methods.
I would like the Boundary pointer to persist until I say delete. Is there any way of doing this without allocating the Boundary to the heap?
EDIT
In response to the suggestion for using const& Game
It would appear that I have to change my Entity header to the following
Entity.h
#pragma once
#include <glm\glm\glm.hpp>
#include "Game.h"
// Forward declarations
class Game;
class Entity
{
public:
// Make destructor virtual as this is a base class
virtual ~Entity(void);
// '= 0' means pure virtual function (like 'abstract' in C#)
// This means they do not have to be declared in the source file '.cpp'
virtual void draw(float dt) = 0;
int getID();
virtual glm::vec3 getPosition() = 0;
virtual void update(float dt) = 0;
protected:
explicit Entity(const Game &game); // Abstract base constructor
Game m_game;
int m_id; // Unique ID
};
Doesn't the Game m_game allocate an instance of the Game class to the stack? How should it be declared in the header if it to represent a reference?
EDIT 2
If I store a protected reference to the Game class in the base Entity class const Game &m_game I cannot seem to access a global member of the Game class g_wireShapeDrawer in derived classes.
class Game
{
public:
GL_WireShapeDrawer g_wireShapeDrawer;
Game(void);
~Game(void);
void init();
void draw(float dt);
void handleInput(float dt);
void loadContent();
void update(float dt);
};
For example I get the following error when trying to access a global member in the draw method of the derived Boundary class source
void Boundary::draw(float dt)
{
m_game.g_wireShapeDrawer.drawPlane(glm::vec3(0, 1, 0), 0.0f, glm::vec4(1, 1, 1, 1));
}
error C2662: 'GL_WireShapeDrawer::drawPlane' : cannot convert 'this' pointer from 'const GL_WireShapeDrawer' to 'GL_WireShapeDrawer &
Why is this?
The Game object should never be deleted from any Entity or derived class. It should be one of the last things to be deallocated before the application shuts down.
You should pass it to your Entity classes as a Game&. Why? Because you only have one instance of the Game, so there is no need to reset what it points to, and it always should be valid (since the game will exist before the Entity objects do).
Another option is to implement the Singleton Pattern in your Game class, and access it like this Game::GetInstance().m_dynamicsWorld->removeRigidBody(m_body);
As per your edit, you can create an Entity using the initializer list. This way you can store const members, like so:
class Entity
{
protected:
explicit Entity(Game &game) : m_game(game) {}
private:
Game& m_game;
}
Your design is flawed. You need to clearly state (through your design) who owns the pointer. If Entity owns the pointer then it should deallocate it in its destructor as you are doing (better yet; just wrap it in a std::unique_ptr). If it does not own the pointer then simply don't deallocate it.
You cannot have it both ways. You're using a shared_ptr, so that implies multiple "owners" and, once the last owner is done with it, the memory will be deallocated. Again, you needs to clearly design around who owns this memory.
Judging from your code, it seems like Entity does not really own the Game*. It needs it for implementation reasons, but should not be responsible for its deallocation.
on a side note, you are violating The Rule of Three.
Related
(sorry for my bad english)
I have a base class with vector of pointers on Drawable objects in it and method draw() that uses data from this vector.
class GameObject
{
protected:
std::vector<Drawable*> drawable;
...
void GameObject::draw() { for (const auto& object : drawable) window.draw(*object); }
In the derived classes I want to have an ability to add some Drawable objects
class Player : public GameObject
{
protected:
RectangleShape shape;
...
Player::Player(float x, float y, float z)
{
shape.setPosition [...]
drawable.push_back(&shape);
...
and draw them using method of base class pointer
std::vector<GameObject*> gameObjects;
...
for (auto& gameObject : gameObjects) gameObject->draw();
The program crashes (I think because the base class don't know anything about vector data in derived class).
I understand that I could make this method pure virtual and define it in the derived classes, but it's not that convenient. Maybe there is another way more similar to this?
upd:
Level::Level()
{
player = Player(500.f, 500.f); //Player player; in header file
gameObjects.push_back(&player);
}
void Level::display()
{
for (auto gameObject : gameObjects) gameObject->draw();
}
The problem is in the code added by your edit -- it looks like my crystal ball is working today.
You're creating a temporary Player and moving it into the player member variable. That ends up with a vector holding the address of the shape inside the temporary Player, which is immediately destroyed, leaving a dangling pointer.
Use a ctor-initializer-list to avoid the move:
Level::Level()
: player(500.f, 500.f /* where did Z go? */)
{
gameObjects.push_back(&player);
}
And disable the assignment operators to prevent doing this by accident in other places:
class Player
{
// ...
Player& operator=(const Player&) = delete;
Player& operator=(Player&&) = delete;
};
I'm new to C++ and i'm having a hard time figuring out what's wrong with my virtual functions. So, here's what i have:
GEntity.h
class GEntity
{
public:
//...
virtual void tick(void);
virtual void render(void);
//...
};
GEntity.cpp
//...
void GEntity::tick(void){}
void GEntity::render(void){}
//...
GLiving.h
class GLiving : public GEntity
{
public:
//...
virtual void tick(void);
virtual void render(void);
//...
};
GLiving.cpp
//...
void GEntity::tick(void){}
void GEntity::render(void){}
//...
Then i have other classes that derive from GLiving (Player, Enemy) which implement their own versions of this two methods:
Player.h
class Player : public GLiving
{
public:
//...
void tick(void);
void render(void);
//...
};
Player.cpp
//...
void GEntity::tick(void)
{
//Here there's some actual code that updates the player
}
void GEntity::render(void)
{
//Here there's some actual code that renders the player
}
//...
Now, if i declare an object of class Player, and call the render/tick method, everything goes well, but i am in a situation in which i add my player to an arraylist (a struct i created) of GEntity, and then, when i get it back, i get it as a GEntity, and i need to call the render/tick methods without knowing it's derived class...
I've tried with the code above, but i get an access violation in the line where i call either the render or tick method, on the extracted GEntity...
...is what i want even possible to achieve?
(sorry if my english is not so good, but i'm italian)
If you have an array of GEntity then, each time you "add" a derived type, the equivalent of this happens:
GEntity g;
Player p;
g = p; // object slicing, you assigned a Player to a GEntity object.
g.render(); // GEntity::render() gets called
On the other hand, you can use a pointer to a base class to access a derived method:
GEntity* g;
Player p;
g = &p;
g->render(); // calls Player::render()
So a way to deal with polymorphism in containers is to have arrays/containers of (preferably smart) pointers to the base class. This example uses raw pointers for simplicity, but you should use smart pointers in real code:
std::vector<CEntity*> entities;
entities.push_back(new Player);
entities.push_back(new GLiving);
// some c++11
for ( auto e : entities) {
e->render();
}
I would like to store a pointer to the main Game class in my abstract Entity class.
Entity.h
#include "Game.h"
class Entity
{
public:
Entity(Game* game);
~Entity(void);
virtual void Draw(float dt) = 0;
virtual void Update(float dt) = 0; // '= 0' means pure virtual function (like 'abstract' in C#)
protected:
Game* m_game; // Missing type specifier error C4430
};
Entity.cpp
#include "Entity.h"
Entity::Entity(Game* game)
{
m_game = game;
}
Entity::~Entity(void)
{
}
I should then be able to instantiate a derived class and pass the Game class reference into the constructor so that it is passed to the base class where it is stored:
Boundary.h
#include "Entity.h"
class Boundary : public Entity
{
public:
Boundary(Game* game);
~Boundary(void);
// Override pure virtual functions
void Draw(float dt);
void Update(float dt);
};
The Boundary constructor can then use the referenced Game class in order to add itself to a list:
#include "Boundary.h"
Boundary::Boundary(Game* game) : Entity(game)
{
// Add entity to the main entity list
game->m_entities->push_back(*this);
}
Boundary::~Boundary(void)
{
}
void Boundary::Draw(float dt)
{
// Call the base class as follows (C# equivalent: 'base.Draw(dt)')
//Entity::Draw(dt);
}
void Boundary::Update(float dt)
{
}
This causes 3 kinds of problems:
game->m_entities->push_back(*this);
error C2663: 'std::list<_Ty,_Ax>::push_back' : 2 overloads have no legal conversion for 'this' pointer
Game* m_game; in Entity.h
error C4430: missing type specifier - int assumed
list<Entity>* m_entities; in Game.h
error C2065: 'Entity' : undeclared identifier
Entity(Game* game); in Entity.h
error C2061: syntax error : identifier 'Game'
The C# equivalent of what I am trying to achieve is:
public abstract class Entity
{
protected Game game;
public abstract void Draw(float dt);
public abstract void Update(float dt);
}
public class Boundary : Entity
{
public Boundary(Game game)
{
this.game = game;
game.Entities.Add(this);
}
public override void Draw(float dt)
{
}
public override void Update(float dt)
{
}
}
Where have I gone wrong?
EDIT:
Game.h
#include "btBulletDynamicsCommon.h"
//#include "LinearMath\btQuaternion.h"
#include <list>
using namespace std; // Required for list
class Entity; // Forward declaration
class Game
{
public:
list<Entity>* m_entities;
Game(void);
~Game(void);
void init();
void draw(float dt);
void loadContent();
void update(float dt);
private:
class btDefaultCollisionConfiguration* m_collisionConfiguration;
class btCollisionDispatcher* m_dispatcher;
class btDiscreteDynamicsWorld* m_dynamicsWorld;
class btBroadphaseInterface* m_overlappingPairCache;
class btSequentialImpulseConstraintSolver* m_solver;
void exitPhysics();
void initPhysics();
};
EDIT 2:
The only problem I am left with now is trying to refer to game in the constructor:
Boundary::Boundary(Game *game)
: Entity(game) // Initialise base
{
// Add entity to the main entity list
game->m_entities->push_back(*this); // ERROR
}
The base class suffers from the same problem
Entity::Entity(Game* game)
: m_game(game) // Initialise members
{
m_game->m_entities->push_back(this); // ERROR here too
}
post-edit
This line in Game.h:
list<Entity>* m_entities;
declares a pointer to a list of Entity instances. Apart from the fact that you can't use this list until you've seen the definition of Entity (which isn't a problem here), it also means that any Entity you put into the list will be copied. Since you're using subclasses of Entity, this will slice the object and only copy the base-class part. So, your list is not polymorphic. And, every time you create a Boundary (or whatever), it tries to add a copy of only its Entity base class subobject to the list.
Consider this instead:
list<Entity*> m_entities;
and maybe move the push_back to the base class too:
Entity::Entity(Game *game) : m_game(game)
{
game->m_entities.push_back(this);
}
Boundary::Boundary(Game *game) : Entity(game) {}
(so you don't have to copy that for every subclass).
In general, when you want runtime polymorphism (derived classes and virtual functions) you need to use indirection such as pointers or references. Now that you're storing pointers, it's also a good idea to think about ownership and lifetime (storing smart pointers rather than raw pointers in that entity list might be a good start).
std::list<std::unique_ptr<Entity> > m_entities;
Oh, and if you're deleting derived types via a base class indirection (like here), the base class destructor should be declared virtual as well.
pre-edit
The missing type specifier error is your first clue: the compiler can't figure out what Game is when you refer to it in the definition of Entity.
Since you're including Game.h, either there's a problem with that header, or a circular dependency (ie, Game.h also includes Entity.h).
However, you don't need to include Game.h there at all:
Entity.h
#ifndef USER1423893_ENTITY_H
#define USER1423893_ENTITY_H
class Game; // forward declaration
class Entity
{
public:
virtual ~Entity(void);
virtual void Draw(float dt) = 0;
virtual void Update(float dt) = 0;
protected:
explicit Entity(Game* game);
Game* m_game;
};
#endif
Entity.cpp
#include "Entity.h"
Entity::Entity(Game* game) : m_game(game)
{
}
What happens now you've fixed that error?
In C++, how can I declare an interface s.t. I can use it as shown below:
/** Enemy "Interface" */
Class Enemy {
Enemy();
virtual ~Enemy();
virtual void doStuff() = 0;
};
/** Enemy of type 1 */
Class Enemy_type1 : public Enemy {
Enemy_type1();
virtual ~Enemy_type1();
virtual void doStuff() {
// different for every type of enemy
}
};
/** Add an enemy to EnemyManager */
void EnemyManager::addEnemy(Enemy * e) {
this->enemies.push_back(*e); // declared as vector<Enemy> enemies;
}
First, you'll have to (or at least want to) make the functions that make up your interface public:
class Enemy {
public:
Enemy();
virtual ~Enemy();
virtual void doStuff() = 0;
};
Then you'll inherit from it (C++ doesn't have "interfaces" and "classes" as separate concepts).
class Emeny_type1 : public Enemy {
// ...
};
Finally, since these are polymorphic types, you'll want to create a collection of pointers to enemies, not of actual Enemy objects:
void EnemyManager::addEnemy(Enemy const *e) {
enemies.push_back(e);
}
This does raise the issues of object lifetime and ownership (which mostly aren't issues in Java). When you add an item to the collection, you'll need to ensure that it's not destroyed as long as you're going to use it, and is destroyed once you're done with it (e.g., when an enemy has been defeated, you might want to remove it). You need to decide whether the EnemyManager is going to delete enemies that are no longer needed, or some other code. If the EnemyManager is going to delete them, you may need (or want) to add a clone function to your Enemy interface for it to get a copy of the object being added to the collection.
Edit: based on your comment, you're not quite sure how to use the Enemy "interface" of a pointer you've stored in your collection. Fortunately, that's fairly simple, something like this:
for (int i=0; i<enemies.size(); i++)
enemies[i]->doStuff();
/* Enemy Interface (Abstract Base Class)
This goes in a header, say Enemy.hpp
*/
class Enemy {
public: // note default access is private in classes
Enemy();
virtual ~Enemy();
virtual void doStuff() = 0;
};
/* Add an enemy to EnemyManager.
The interface is a type, and is known!
It doesn't need to know anything about the subclasses
which implement the interface.
*/
void EnemyManager::addEnemy(Enemy * e) {
this->enemies.push_back(*e); // vector of Enemy POINTERS
}
/* Enemy of type 1.
This would go in say Enemy1.hpp - it depends on Enemy.hpp,
but EnemyManager doesn't need to know anything about this.
*/
Class Enemy_type1: public Enemy {
public:
Enemy_type1();
virtual ~Enemy_type1();
virtual void doStuff();
};
/* ... and in a .cpp file somewhere ... */
Enemy_type1::Enemy_type1() : Enemy()
{
// this is redundant unless you have some work for it to do
}
Enemy_type1::~Enemy_type1()
{
}
void Enemy_type1::doStuff()
{
// do your stuff here
}
I have an Entity baseclass which the classes Player and Enemy Inherit.
class Entity
{
public:
virtual void Update(sf::RenderWindow &window) {};
virtual void Draw(sf::RenderWindow &window) {};
};
Both player and enemy contain a sprite object that looks like this:
class Player : Entity
{
public:
sf::Sprite sprite
void Update(sf::RenderWindow &window);
void Draw(sf::RenderWindow &window)
}
Player and Enemy are created inside a vector which is set up like this:
class EntityManager
{
public:
void CollisionCheck();
private:
std::vector<Entity*> entityVector;
}
I'm looking to use a collision detection function of this form:
bool Collision::CircleTest(const sf::Sprite& Object1, const sf::Sprite& Object2)
So I'm trying to do something like this:
void EntityManager::ColCheck()
{
if (Collision::CircleTest(entityVector[0]->sprite, entityVector[1]->sprite))
{
cout << "COLLISION\n";
}
}
This results in the following compile error:
‘class Entity’ has no member named ‘sprite’
I'm unsure how to create a dummy sprite in Entity so that I can access the player and enemy sprites using the above method. Is this possible?
I'm stumped and would greatly appreciate any help anyone can offer!
If everything in your code that derives from Entity has a sprite object, then you should declare that object in the base class.
Not declaring the object in the base class means that there could be a class inheriting from Entity that does not have a sprite object, which means that ColCheck has no valid basis for assuming that elements of entityVector point to something that has a variable called sprite. Make sense?
You probably shouldn't create a dummy unless having a sprite is something ALL entities have.
What you might want is to use a visitor pattern or possibly one of the many multiple-dispatch implementations. Which and what will end up having to be up to you.
If both Player and Enemy classes contain sprite, why not declare it inside Entity? This should solve your problem.
You could make a member function sprite() that is declared as a pure virtual function inside Entity:
class Entity {
public:
virtual void Update(sf::RenderWindow &window) {};
virtual void Draw(sf::RenderWindow &window) {};
virtual sf::Sprite& sprite() = 0;
};
Then, the Player and Enemy implementations would return the sf::Sprite instance variables each has. However, the other posters bring up a valid point; it might make sense to have the sprite be in the base class if all derived classes are going to have one.