简体   繁体   English

从 STL map 迭代器获取字段

[英]Getting a field from an STL map iterator

I have a map container to store certain objects, together with their name and type:我有一个 map 容器来存储某些对象,以及它们的名称和类型:

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

However, in many parts of the code, there are constructions like this:但是,在代码的很多地方,都有这样的构造:

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;
    }
}

Obviously, the many "it->second.second" are not very clear, and unmaintainable.很明显,很多“it->second.second”不是很清楚,而且不可维护。 If it is changed in the future, to support one more field, for example, it will be all broken.以后要是改了,多支持一个领域,比如,就全坏了。 So, I am trying to change them by functions to access the fields, like this:因此,我试图通过函数更改它们以访问字段,如下所示:

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

Similarly, also function getObjName and getObjType.同样,还有 function getObjName 和 getObjType。

It was also suggested to me that it would be more clear to have the iterator returning those fields:有人还向我建议让迭代器返回这些字段会更清楚:

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

But I think that the STL iterators should not be inherited to have those functions, right?但我认为STL迭代器不应该被继承来拥有那些功能,对吧? I see no other way to do it except to create a wrapper for the map and have its own iterator with those functions.除了为 map 创建一个包装器并拥有自己的具有这些功能的迭代器之外,我看不出有其他方法可以做到这一点。

So, what would be the most appropriate option?那么,最合适的选择是什么? Is there any other way to solve this problem that I am not seeing?有没有其他方法可以解决我没有看到的这个问题?

If the biggest problem is maintainability, I would replace the std::pair with a custom class/struct that wraps the ObjType and ObjBase* as one.如果最大的问题是可维护性,我会将 std::pair 替换为将 ObjType 和 ObjBase* 包装为一个的自定义类/结构。

  • it's easy to add a new field in the mix在组合中添加新字段很容易
  • it's easy to access struct fields ObjType and ObjPair访问结构字段 ObjType 和 ObjPair 很容易
  • it's easy to write getters/setters/other functions for a class that handle ObjType and ObjPair很容易为 class 编写处理 ObjType 和 ObjPair 的 getters/setters/其他函数

I'd just make a local copy of the pointer (or reference) -- it'll probably be optimized out anyway:我只是制作指针(或引用)的本地副本——它可能会被优化掉:

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

Use a reference to simplify the syntax.使用引用来简化语法。

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

I'd first question myself on whether ObjType is mandatory there.我首先会问自己 ObjType 是否是强制性的。 If the aim is just to tell what kind of class is actually pointed by the second ObjBase* parameter of the pair, use dynamic_cast and get rid of the pair.如果目的只是告诉该对的第二个 ObjBase* 参数实际指向哪种 class,请使用dynamic_cast并摆脱该对。

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

No more second.second in the code then:代码中不再有second.second

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

And when you need to test the actual type of the object:而当你需要测试object的实际类型时:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM