3

所以我有一个充满游戏所有对象的向量;诸如玩家对象、敌人对象、墙壁等之类的东西……向量中的所有事物都是 的子对象Framework,所以我制作了向量类型Framework,因为这对它们来说是最接近通用数据类型的东西。

问题是它没有从它存储的对象中运行覆盖的函数。所以我用谷歌搜索发现我显然是通过将它们存储为对象切片来进行的Framework。所以我的问题是,如何将所有这些对象存储在一个列表中?

仅供参考,这是调用应该被覆盖的函数的地方。

for (vector<Framework>::iterator num = gameObjects.begin(); num != gameObjects.end(); ++num)
{
    //The current thing
    Framework currentObject = *num;
    currentObject.frameEvent();
    currentObject.frameEndEvent();
    currentObject.drawEvent();
}

提前致谢。

4

8 回答 8

7

您必须存储指针 ( Framework*) 或std::shared_ptr< Framework >(可能std::unique_ptr< Framework >)实例。这允许使用虚拟调用和后期绑定——这意味着当您引用您的对象时,将在运行时确定要调用的正确函数。不要忘记让你的功能virtual

然后,您的代码(以类似的方式)

for (vector< Framework* >::iterator num = gameObjects.begin(); num != gameObjects.end(); ++num)
{
  Framework* currentObject = *num;
  currentObject->frameEvent();
  currentObject->frameEndEvent();
  currentObject->DrawEvent();
}

但是,我会推荐这样的东西(需要 c++11)

vector< std::unique_ptr< Framework > > gameObjects;

...

for (auto & currentObject : gameObjects)
{
  currentObject->frameEvent();
  currentObject->frameEndEvent();
  currentObject->DrawEvent();
}

无论使用哪种类型,最后一个(循环范围)都应该起作用(您可以使用普通指针或 shared_ptr 或 unique_ptr 如示例所示)。

如果您有兴趣使用unique_ptr,请注意,为了将这些存储在 上std::vector,您必须使用,因为(顾名思义)std::move只能有一个实例。如有问题,请参阅此答案std::unique_ptr

于 2015-08-02T21:03:15.727 回答
2

您必须使用std::vector<Framework*>std::vector<std::unique_ptr<Framework>>(或您选择的智能指针)来避免对象切片。

代码示例:

std::vector<std::unique_ptr<Framework>> gameObjects;

gameObjects.push_back(std::make_unique<Player>(/**/));
gameObjects.push_back(std::make_unique<Wall>(/**/));

接着

for (auto& currentObject : gameObjects)
{
    currentObject->frameEvent();
    currentObject->frameEndEvent();
    currentObject->drawEvent();
}
于 2015-08-02T21:03:40.827 回答
2

存储指向Framework并利用多态性的指针。

// Base class
class Framework {
    // Make pure virtual if nothing is done here.
    virtual void frameEvent(); // = 0;

    // To ensure the derived instances are deleted properly.
    virtual ~Framework(); // = default;
};

// Some specialized class
class SomeObject : public Framework {
    void frameEvent() override; // C++11 style override.
};

std::vector<std::unique_ptr<Framework>> objects;

// Add a new SomeObject to the list
objects.emplace_back(new SomeObject());
于 2015-08-02T21:07:16.120 回答
1

好吧,直接的答案是 - 你没有。或者你会得到你已经遇到过的对象切片。您需要使用 C++ 的多态能力并将对象的公共接口存储在向量中。稍后您可以根据实际对象类型调用具有不同实现的接口函数来调用所需的行为。

于 2015-08-02T21:04:14.803 回答
1

你要使frameEventframeEndEventdrawEvent虚在Framework。然后,存储std::shared_ptr在您的向量中:

std::vector<std::shared_ptr<Framework>> objects;
objects.push_back(new GameObject());

for (vector<Framework>::iterator num = gameObjects.begin(); num != gameObjects.end(); ++num)
{
  //The current thing
  const Framework& currentObject = **num; // reference, don't copy anything if you don't need to
  currentObject.frameEvent();
  currentObject.frameEndEvent();
  currentObject.drawEvent();
}

请注意,只要不使用需要复制元素的操作,unique_ptr就可以将 a 存储在向量中。

另一种选择,如果你不能使函数虚拟并且知道你正在处理什么类型的对象,你可以先转换然后调用非虚拟函数:

const PlayerObject& player = static_cast<const PlayerObject&>(*objects[0]);
player.frameEvent();
player.frameEndEvent();
player.drawEvent();
于 2015-08-02T21:12:27.380 回答
1

您需要存储指向对象的指针。如果你有,C++11那么理想情况下你将使用std::unique_ptr存储它们(假设你有一个主向量)。

C++03

std::vector<Framework*> gameObjects;

for(std::vector<Framework*>::iterator num = gameObjects.begin();
    num != gameObjects.end(); ++num)
{
    (*num)->frameEvent();
    (*num)->frameEndEvent();
    (*num)->drawEvent();
}

C++ 11

std::vector<std::unique_ptr<Framework>> gameObjects;

for(auto& num: gameObjects)
{
    num->frameEvent();
    num->frameEndEvent();
    num->drawEvent();
}
于 2015-08-02T21:12:31.643 回答
0

将指针存储在向量中,而不是实际实例中。

于 2015-08-02T21:03:29.923 回答
0

另一种可能更快的方法是将它们存储在单独的向量中。由于更高的缓存效率,它可以快 50 倍。

于 2015-09-09T12:42:44.350 回答