【问题标题】:How to retrieve multiple inherited types from a collection in C++?如何从 C++ 中的集合中检索多个继承的类型?
【发布时间】:2017-06-06 14:36:06
【问题描述】:

假设您有一个包含 Item 类型的 std::vector 类,并且您存储继承的项目类型:武器、药水、盔甲等。您如何将项目检索为继承类而不是基类?

【问题讨论】:

  • 您需要一个指针/引用向量以避免切片。然后您需要某种方法来检测对象的类型,RTTI 或类型标志。但多态性的全部意义在于您不需要知道确切的类型。

标签: c++


【解决方案1】:

如何将项目检索为继承类而不是基类?

这说明你需要闭集多态,由std::variantboost::variant提供。

using Entity = std::variant<Weapon, Potion, Armor>;
// An `Entity` is either a `Weapon`, a `Potion`, or an `Armor`.

std::vector<Entity> entities;

struct EntityVisitor
{
    void operator()(Weapon&);
    void operator()(Potion&);
    void operator()(Armor&);
};

for(auto& e : entities)
{
    std::visit(EntityVisitor{}, e);
    // Call the correct overload depending on what `e` is.
}

【讨论】:

  • 有趣。例如,在 for 循环中,我怎么知道 'è' 现在是 Weapon 类型?还是 visit() 把 e 变成了 Weapon?
  • @Phil:visit 为您处理。如果e 是武器,那么EntityVisitor::operator()(Weapon&amp;) 将被调用。
  • 太棒了。感谢您的帮助。
  • variantvisit 是否获得批准?我不知道他们把它变成了标准。值得注意的是en.cppreference.com 也不...
  • @JonathanMee - 它们在最新的标准草案中。 eel.is/c++draft/variant
【解决方案2】:

你的设计有一股难闻的味道。存储item* 的代价是不得不在vector 之外管理它们。 vector&lt;item*&gt; 的唯一良好动机是使用 items polymorphically。通过尝试检测您所证明的类型,您没有以多态方式使用它们。

更好的解决方案是将这些项目存储在单独的向量中,而不是公共的vector&lt;item*&gt; items,所以vector&lt;weapon&gt; weaponsvector&lt;potion&gt; potionsvector&lt;armor&gt; armors

所以请不要使用这个代码,但是给定vector&lt;item*&gt; items你可以这样做:

for(auto i : items) {
    if(dynamic_cast<weapon*>(i) != nullptr) {
        auto iWeapon = static_cast<weapon*>(i);
        // work with weapon here
    } else if(dynamic_cast<potion*>(i) != nullptr) {
        auto iPotion = static_cast<potion*>(i);
        // work with potion here
    } else {
        assert(dynamic_cast<armor*>(i) != nullptr);
        auto iArmor = static_cast<armor*>(i);
        // work with armor here
    }
}

【讨论】:

  • 单独的向量确实使它更干净。我也会试试这个。谢谢。
  • @Phil 通常,当您看到所有dynamic_casts 时,提示应该使用模板化。
猜你喜欢
  • 1970-01-01
  • 2010-11-08
  • 1970-01-01
  • 2021-05-28
  • 2016-08-27
  • 2011-05-19
  • 1970-01-01
  • 1970-01-01
  • 2010-11-24
相关资源
最近更新 更多