C ++在可以从派生类访问的抽象基类中存储类指针?

时间:2012-08-22 22:15:59

标签: c++ polymorphism derived-class

我想在抽象的实体类中存储指向主Game类的指针。

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)
{

}

然后我应该能够实例化派生类并将Game类引用传递给构造函数,以便将它传递给存储它的基类:

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);
};

然后,Boundary构造函数可以使用引用的Game类将其自身添加到列表中:

#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)
{

}

这会导致3种问题:

game->m_entities->push_back(*this);

  

错误C2663:'std :: list< _Ty,_Ax> :: push_back':2个重载没有'this'指针的合法转换

Entity.h中的

Game* m_game;

  

错误C4430:缺少类型说明符 - 假设为int

Game.h中的

list<Entity>* m_entities;

  

错误C2065:'实体':未声明的标识符

Entity.h中的

Entity(Game* game);

  

错误C2061:语法错误:标识符'Game'

我想要达到的C#相当于:

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)
    {

    }
}

我哪里出错?

编辑:

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();
};

编辑2:

我现在唯一的问题是尝试在构造函数中引用游戏:

    Boundary::Boundary(Game *game) 
    : Entity(game)                  // Initialise base
{
    // Add entity to the main entity list
    game->m_entities->push_back(*this);      // ERROR
}

基类遇到同样的问题

    Entity::Entity(Game* game) 
    : m_game(game)                  // Initialise members
{
    m_game->m_entities->push_back(this);     // ERROR here too
}

1 个答案:

答案 0 :(得分:3)

- 编辑后

Game.h中的这一行:

list<Entity>* m_entities;

声明指向实体实例列表的指针。除了你看到实体的定义(这里不是问题)之前你不能使用这个列表这一事实,这也意味着你放入列表的任何实体都将被复制。由于您正在使用Entity的子类,因此这将slice该对象并仅复制基类部分。因此,您的列表不是多态。并且,每次创建边界(或其他)时,它都会尝试将副本其实体基类子对象添加到列表中。

请考虑一下:

list<Entity*> m_entities;

并且可能将push_back移动到基类:

Entity::Entity(Game *game) : m_game(game)
{
    game->m_entities.push_back(this);
}

Boundary::Boundary(Game *game) : Entity(game) {}

(所以你不必为每个子类复制它。)

通常,当您需要运行时多态(派生类和虚函数)时,您需要使用间接,例如指针或引用。现在您正在存储指针,考虑所有权和生命周期也是一个好主意(在该实体列表中存储智能指针而不是原始指针可能是一个好的开始)。

std::list<std::unique_ptr<Entity> > m_entities;

哦,如果您通过基类间接删除派生类型(如此处),则基类析构函数也应声明为虚拟。


预编辑

缺少类型说明符错误是您的第一个线索:当您在Game的定义中引用它时,编译器无法确定Entity是什么。< / p>

由于您要包含Game.h,因此该标头存在问题或循环依赖(即Game.h还包括Entity.h)。

但是,您根本不需要包含Game.h

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)
{
}

现在你修复了那个错误会发生什么?