【发布时间】:2012-09-12 06:00:47
【问题描述】:
在 Game 类函数中,我将 Boundary 类分配给堆栈
void Game::loadContent()
{
Boundary b(this, body);
}
边界类有一个指向主游戏类的指针和一个指向刚体的指针。我不确定是否应该为每个使用参考?由于稍后解释的原因,此处的一些清晰度会有所帮助。
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);
};
DynamicEntity 类分配主体并在其析构函数中处理指针删除。
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 析构函数
DynamicEntity::~DynamicEntity(void)
{
m_game->m_dynamicsWorld->removeRigidBody(m_body);
delete m_body;
}
DynamicEntity 派生自所有名为 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
};
我不能在这个类的析构函数中对 Game 类指针调用 delete,这就是为什么我不确定作为指针传递是否是正确的方法(而不是引用)?
Entity::~Entity(void)
{
// Derived class destructors are called first
delete m_game; // ERROR
}
Entity 类添加一个指向自身的指针,该指针可以通过 Game 类中的列表访问(对于在主 Game 类中迭代和调用 Entity 函数很有用)。
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));
}
我遇到的主要问题是,一旦 Game::loadContent() 方法完成,就会为 Entity 类调用析构函数。这会破坏存储在列表中的 *shared_ptr*,并在尝试调用任何虚拟方法时发生错误。
我希望边界指针一直存在,直到我说删除。有没有办法在不将边界分配给堆的情况下做到这一点?
编辑
响应使用const& Game的建议
看来我必须将我的实体标头更改为以下内容
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
};
Game m_game 不是将 Game 类的实例分配给堆栈吗?如果它代表一个引用,它应该如何在标题中声明?
编辑 2
如果我在基实体类 const Game &m_game 中存储对 Game 类的受保护引用,我似乎无法在派生类中访问 Game 类 g_wireShapeDrawer 的全局成员。
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);
};
例如,当我尝试在派生的 Boundary 类源的 draw 方法中访问全局成员时出现以下错误
void Boundary::draw(float dt)
{
m_game.g_wireShapeDrawer.drawPlane(glm::vec3(0, 1, 0), 0.0f, glm::vec4(1, 1, 1, 1));
}
错误 C2662:“GL_WireShapeDrawer::drawPlane”:无法将“this”指针从“const GL_WireShapeDrawer”转换为“GL_WireShapeDrawer &
这是为什么?
【问题讨论】:
-
...另一个程序员用裸指针弄糊涂了。道德:不要使用裸指针。您刚刚发现了原因。
-
你知道不鼓励使用裸指针是件好事,但我相信程序员在摒弃它们之前应该充分理解它们。它们是语言的基本组成部分。
-
@KerrekSB:我不想和不懂这种语言的人一起工作。你会?抽象是伟大的,如果你了解它们下面发生的事情。没有抽象是无泄漏的,更好的程序员知道他们的代码实际上在做什么。
-
@Aesthete:我并不是说你不应该理解指针。你只是不应该使用它们,至少不要以这种的方式。指针当然有特定用途,但大多数人可以做更多的克制......
-
我也不明白为什么有人会拒绝这个问题。
标签: c++ pointers heap-memory stack-memory