【发布时间】:2011-08-13 17:34:53
【问题描述】:
在我的游戏中,我创建了一个名为 Entity 的基类,我将其存储在一个集合中以供处理。我所有的游戏对象都派生自这个类,在我的初始化函数中将派生的指针类型添加到集合中没有问题。
问题在于从实体的Step() 函数中添加新元素。现在,在深入探讨之前,我将向您展示一些简化的代码:
class GameState
{
public:
GameState();
~GameState();
...
set<Entity*> entities;
void Add(Entity* e);
void Remove(Entity* e);
protected:
set<Entity*> added, removed;
};
class Entity
{
public:
Entity();
Entity(GameState* parent);
virtual ~Entity();
virtual void Step(const sf::Input& input);
...
virtual void Destroy();
protected:
GameState* game;
};
GameState 中的 Add 和 Remove 函数只需将参数 e 分别添加到 added 和 removed 集合中。在主循环中(GameState 中的其他地方),我在处理之前将元素从added 移动到entities,在处理之后我从entities 中删除来自removed 的元素。这确保了entities 在迭代期间不会被修改。
添加/删除功能非常简单:
void GameState::Add(Entity* e)
{
added.insert(e);
}
void GameState::Remove(Entity* e)
{
removed.insert(e);
}
每个派生实体都会在其构造函数中传递一个指向 GameState 的指针,并将其保存为 game。所以理论上从 Step 函数我应该能够通过像game->Remove(this); 这样的简单调用来添加和删除实体,但是我得到了一个段错误。经过一夜的谷歌搜索并且一无所获,我能够通过像这样实现Entity::Destroy() 来解决(部分)问题:
void Entity::Destroy()
{
game->Remove(this);
}
所以我的第一个问题是:为什么this 在基类中而不在派生类中工作?
让我更困惑的是Add()。为什么Add(new Explosion(16,16,this)) 在 GameState 中可以工作,而game->Add(new Explosion(16,16,game)) 在我的对象中却不能工作?
我通过 gdb 运行它,它告诉我:
Program received signal SIGSEGV, Segmentation fault.
At c:/program files (x86)/codeblocks/mingw/bin/../lib/gcc/mingw32/4.4.1/include/c++/bits/stl_tree.h:482
引发错误的代码是:
_Link_type
_M_begin()
{ return static_cast<_Link_type>(this->_M_impl._M_header._M_parent); } //this line
总而言之,我不知道为什么我的指针会破坏 STL ......而且我有一种严重的感觉,我错过了一些非常基本的东西并导致所有这些头痛。谁能给我建议?
【问题讨论】:
-
这么少的代码。使用
std::set时无代码。 -
你如何保持主实体数组,一个你正在跨过的?
-
@Nawaz:我对其进行了编辑以显示 std::set 如何在辅助函数中使用。请注意,这些是我编写的堆栈跟踪中的最后几行。我传递给它们的指针应该是有效的,因为我只传递指向实体子类的指针,但由于某种原因它们不是。
-
@elevener 我使用 std::set
而不是数组 -
@aeron005 - 在这种情况下,你如何删除你的对象?
标签: c++ inheritance pointers segmentation-fault