首页 文章

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

提问于
浏览
1

我想在我的抽象Entity类中存储一个指向主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'指针的合法转换

Game* m_game; 在Entity.h中

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

在Game.h中 list<Entity>* m_entities;

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

Entity(Game* game); 在Entity.h中

错误C2061:语法错误:标识符'游戏'

我想要实现的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 回答

  • 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;
    

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


    预编辑

    丢失的类型说明符错误是您的第一个线索:当您在 Entity 的定义中引用它时,编译器无法确定 Game 是什么 .

    由于您包含 Game.h ,因此该 Headers 存在问题,或者循环依赖(即 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)
    {
    }
    

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

相关问题