【问题标题】:Getting a field from an STL map iterator从 STL 映射迭代器中获取字段
【发布时间】:2012-04-03 22:01:18
【问题描述】:

我有一个地图容器来存储某些对象,以及它们的名称和类型:

typedef std::map<std::string, std::pair<ObjType, ObjBase*> > ObjContainer;

但是,在代码的很多部分,都有这样的结构:

ObjContainer::iterator it = mObjContainer.find(name);
if (it != mObjContainer.end()) {
    if (it->second.second) {
        it->second.second->setObj2Default();
        delete it->second.second;
        it->second.second = 0;
    }
}

显然,许多“it->second.second”不是很清楚,而且无法维护。 如果以后改了,比如多支持一个领域,那就全都坏掉了。 因此,我试图通过函数来​​更改它们以访问字段,如下所示:

ObjBase*& getObjPtr(ObjContainer::iterator it) {
    return it->second.second;
}

同样,getObjName 和 getObjType 函数也是如此。

还有人建议我让迭代器返回这些字段会更清楚:

 it.objPtr();
 it.objName();
 it.objType();

但我认为不应继承 STL 迭代器以具有这些功能,对吗?除了为地图创建一个包装器并使用这些函数拥有自己的迭代器之外,我没有其他方法可以做到这一点。

那么,最合适的选择是什么?有没有其他方法可以解决我没有看到的这个问题?

【问题讨论】:

  • 你为什么不直接使用结构而不是一对,并按照你想要的方式命名你的字段?
  • @Spidey:如果库已经提供了一个完全可用的类定义,为什么还要推出自己的类定义?
  • 你可以用 acessors 包装它们。至少你会侥幸不使用pair.first、pair.second、pair->second->second等。

标签: c++ map iterator std-pair


【解决方案1】:

如果最大的问题是可维护性,我会将 std::pair 替换为将 ObjType 和 ObjBase* 包装为一个的自定义类/结构。

  • 在组合中添加新字段很容易
  • 很容易访问结构字段 ObjType 和 ObjPair
  • 为处理 ObjType 和 ObjPair 的类编写 getter/setter/其他函数很容易

【讨论】:

    【解决方案2】:

    我只是制作指针(或引用)的本地副本——无论如何它可能会被优化:

    ObjContainer::iterator const it = mObjContainer.find(name);
    if (it != mObjContainer.end())
    {
        ObjBase * & p = it->second.second;
        if (p) { p->foo(); delete p; p = NULL; }
    }
    

    【讨论】:

      【解决方案3】:

      使用引用来简化语法。

      ObjContainer::iterator it = mObjContainer.find(name);
      if (it != mObjContainer.end()) {
          std::pair<ObjType, ObjBase*> & ref = it->second;
          if (ref.second) { // ...
      

      【讨论】:

        【解决方案4】:

        我首先要问自己 ObjType 是否是强制性的。 如果目的只是判断该对的第二个 ObjBase* 参数实际指向的是哪种类,请使用 dynamic_cast 并删除该对。

        typedef std::map<std::string, ObjBase*> ObjContainer;
        

        代码中不再有second.second

        ObjContainer::iterator it = mObjContainer.find(name);
        if (it != mObjContainer.end()) {
            if (it->second) {
                it->second->setObj2Default();
                delete it->second;
                it->second = NULL;
            }
        }
        

        而当你需要测试对象的实际类型时:

        ObjContainer::iterator it = mObjContainer.find(name);
        if (it != mObjContainer.end()) {
            if (ChildObj* p_Child = dynamic_cast<ChildObj*>(it->second)) {
                // Work on p_Child...
            }
        }
        

        【讨论】:

        • 不,ObjType 是必需的,因为有时 ObjBase* 会为空,它们 ObbType 可用于使用工厂构建新实例。
        猜你喜欢
        • 2011-04-02
        • 2011-05-29
        • 1970-01-01
        • 2011-05-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-05-11
        • 1970-01-01
        相关资源
        最近更新 更多