如何在单个向量中存储不同的 类?

How do I store different classes in a single vector?

所以我有一个向量,里面装满了我游戏的所有对象;诸如玩家对象、敌人对象、墙壁等...矢量中的所有事物都是 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();
}

提前致谢。

您必须存储指针 (Framework*),或 std::shared_ptr< Framework >(可能 std::unique_ptr< Framework >)实例。这允许使用虚拟调用和 late binding - 这意味着当您引用您的对象时,将在运行时确定要调用的正确函数。不要忘记让你的函数 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(顾名思义)。 Consult this answer 以防出现问题。

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

您必须使用 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();
}

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

存储指向 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());

您必须在 Framework 中将 frameEventframeEndEventdrawEvent 虚拟化。然后,将 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 存储在向量 as long as you don't use operations that require copying elements 中。

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

const PlayerObject& player = static_cast<const PlayerObject&>(*objects[0]);
player.frameEvent();
player.frameEndEvent();
player.drawEvent();

您需要为您的对象存储 指针 。如果你有 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();
}

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