2

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

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 迭代器以具有这些功能,对吗?除了为地图创建一个包装器并拥有自己的带有这些函数的迭代器外,我没有其他方法可以做到这一点。

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

4

4 回答 4

4

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

  • 在组合中添加新字段很容易
  • 访问结构字段 ObjType 和 ObjPair 很容易
  • 为处理 ObjType 和 ObjPair 的类编写 getter/setter/其他函数很容易
于 2012-04-03T22:10:46.707 回答
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; }
}
于 2012-04-03T22:08:57.180 回答
0

使用引用来简化语法。

ObjContainer::iterator it = mObjContainer.find(name);
if (it != mObjContainer.end()) {
    std::pair<ObjType, ObjBase*> & ref = it->second;
    if (ref.second) { // ...
于 2012-04-03T22:09:31.247 回答
0

我首先会问自己 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...
    }
}
于 2012-04-03T22:35:37.457 回答