1

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
}
user1423893
  • 766
  • 4
  • 15
  • 26
  • When using Clang, if I make one change (define `m_entities` as `list` and use `game->m_entities->push_back(this)`) then it compiles just fine. – Lily Ballard Aug 22 '12 at 22:31
  • can you show us "Game.h" as well? – Grzegorz Herman Aug 22 '12 at 22:31
  • the call `m_entities->push_back(*this)` will not do what you want -- it will add a COPY of the current Boundary (and not a pointer to it) to `m_entities`; even if making this copy is possible, it would probably result in an infinite loop – Grzegorz Herman Aug 22 '12 at 22:34
  • you probably also need to forward-declare `class Entity` in Game.h before using it as a template argument to `list<>` – Grzegorz Herman Aug 22 '12 at 22:35

1 Answers1

3

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?

Community
  • 1
  • 1
Useless
  • 64,155
  • 6
  • 88
  • 132
  • I get the following error for `game->m_entities->push_back(*this);` _pointer to incomplete class type is not allowed_ – user1423893 Aug 22 '12 at 22:56
  • This line also produces _error C2027: use of undefined type 'Game'_ and _error C2259: 'Entity' : cannot instantiate abstract class_ – user1423893 Aug 22 '12 at 22:57
  • After reading your answer more carefully and doing some further research I am left with one problem outlined by the second edit (EDIT 2). – user1423893 Aug 23 '12 at 00:32