简体   繁体   English

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

[英]C++ Storing a class pointer in an abstract base class that can be accessed from derived classes?

I would like to store a pointer to the main Game class in my abstract Entity class. 我想在我的抽象Entity类中存储一个指向主Game类的指针。

Entity.h 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 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: 然后我应该能够实例化一个派生类,并将Game类引用传递给构造函数,以便将它传递给存储它的基类:

Boundary.h 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: 然后,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)
{

}

This causes 3 kinds of problems: 这导致3种问题:

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

error C2663: 'std::list<_Ty,_Ax>::push_back' : 2 overloads have no legal conversion for 'this' pointer 错误C2663:'std :: list <_Ty,_Ax> :: push_back':2个重载没有'this'指针的合法转换

Game* m_game; in Entity.h 在Entity.h中

error C4430: missing type specifier - int assumed 错误C4430:缺少类型说明符 - 假定为int

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

error C2065: 'Entity' : undeclared identifier 错误C2065:'实体':未声明的标识符

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

error C2061: syntax error : identifier 'Game' 错误C2061:语法错误:标识符'游戏'

The C# equivalent of what I am trying to achieve is: 我想要实现的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)
    {

    }
}

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: 编辑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: 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. 由于您正在使用Entity的子类,因此将对对象进行切片并仅复制基类部分。 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: 并且也可以将push_back移动到基类:

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

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 ). 由于你包含Game.h ,要么是标题有问题,要么是循环依赖(即Game.h还包括Entity.h )。

However, you don't need to include Game.h there at all: 但是,您根本不需要包含Game.h

Entity.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 Entity.cpp

#include "Entity.h"

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

What happens now you've fixed that error? 现在你修复了那个错误会发生什么?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 C ++:使用抽象类中的指针来访问派生类的方法; 派生类apears也是抽象的 - C++: Use pointer from abstract class for accessing method of derived classes; derived class apears to be abstract as well 在C++中将抽象基类的不同派生类的对象存储在数组中 - Storing objects of different derived classes of an abstract base class in an array in C++ 使用抽象基类C ++中的变量派生的类 - Derived class using variables from abstract base class C++ 多态C ++,尝试访问从抽象基类派生的类的成员函数 - polymorphism c++, trying to access member functions of classes that are derived from abstract base class 指向C ++中派生类的基类指针 - the base class pointer to the derived class in c++ 从抽象基类派生的C ++包装器类,并在另一个也从抽象基类派生的类中调用方法 - C++ wrapper class that is derived from an abstract base class and calls a method in another class that is also derived from the abstract base class C ++访问派生类与基类的指针 - c++ access derived class with a pointer from base class C ++-在运行时从基类指针识别派生类 - C++ - Identify derived class from base class pointer at runtime C++ 从基类指针访问派生类成员 - C++ Access derived class member from base class pointer C ++从派生类指针获取基类对象? - c++ get base class object from derived class pointer?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM