【问题标题】:c++ Map [] operator not foundc++ Map [] 运算符未找到
【发布时间】:2013-08-19 07:54:00
【问题描述】:
void Library::addKeywordsForItem(const Item* const item, int nKeywords, ...)
{
    // the code in this function demonstrates how to handle a vararg in C++

    va_list     keywords;
    char        *keyword;

    va_start(keywords, nKeywords);
    for (int i = 0; i < nKeywords; i++)
    {
        keyword = va_arg(keywords, char*);
        ((Item*)const_cast<Item*>(item))->addKeyword(string(keyword)); 

        ItemSet* itemSet = keywordItems[string(keyword)];
        if (itemSet == NULL)
        {
            itemSet = new ItemSet();
            keywordItems[keyword] = itemSet;
        }
        bool isNull = (itemSet == NULL) ? true : false;
        itemSet->insert(((Item*)const_cast<Item*>(item)));
    }
    va_end(keywords);
}

const ItemSet* Library::itemsForKeyword(const string& keyword) const
{
    return keywordItems[((string)const_cast<string&>(keyword))];
}

在上面的代码中,第一种方法按预期工作。第二种方法没有,并显示错误@“[”

no operator "[]" 匹配这些操作数操作数类型是: const StringToItemSetMap [ std::string ]

StringToItemSetMap 只是 map 的 typedef。我尝试了不同的强制转换,并创建了一个本地字符串变量,但不是运气。甚至像 keywordItems[string("test")];在第二种方法中不起作用,但在第一种方法中起作用。有什么我可能错过的吗?

编辑:

const ItemSet* Library::itemsForKeyword(const string& keyword) const
{
    std::map<std::string, ItemSet*>::const_iterator it = keywordItems.find(keyword);
    if (it != keywordItems.end())
    {
        return it->second;
    }
    return NULL;
}

正如在答案中指出的那样,问题是因为第二种方法是 const 而 map::operator[] 不是。

【问题讨论】:

  • 你试过keywordItems["test"]吗?
  • 我应该问你为什么要做const_cast,然后立即将C风格转换为string...?
  • 不要使用char* 作为映射键。
  • @Dukeling 是的,结果我得到了同样的错误。 cHao 其实这是我在没有想法的时候尝试过的。正如我已经提到的,我尝试输入 string("test") 并得到相同的错误。 Luchian Grigore 我一开始实际上是在使用它,但改用字符串作为键。没有帮助解决错误。
  • 提供SSCCE 总是有帮助的,以防止丢失有用的代码(例如keywordItems 的定义),并让我们可以轻松地尝试看看哪些有效。

标签: c++ map stl operator-keyword


【解决方案1】:

您正在使用覆盖的operator[],它必须对底层映射具有非常量访问权限,因为如果请求的关键位置不存在新条目,它将添加一个新条目。在您的情况下,将添加一个 NULL 指针(不说明原因)。您的成员函数被声明为const,因此映射不可修改。

要么将映射声明为 mutable(不推荐),要么使用迭代器搜索并在搜索返回 keywordItems.end() 时返回 NULL。否则,返回迭代器的对象(it-&gt;second)。

示例

const ItemSet* Library::itemsForKeyword(const string& keyword) const
{
    std::map<std::string, ItemSet*>::const_iterator it =  keywordItems.find(keyword);
    if (it != keywordItems.cend())
       return it->second;
    return nullptr;
}

注意:我强烈建议对地图对象内容使用直接对象,或者至少使用智能指针(例如std::shared_ptr&lt;ItemSet&gt;)。 RAII: 晚餐吃什么。

【讨论】:

  • 感谢您的回答。我用工作代码编辑了区域帖子。我注意到您对 const ItemSet* 进行了动态转换。我不确定为什么那里需要它。你能简单解释一下吗?
  • 或者使用.at(),可以是const;不过需要 C++11 支持。
  • @jM2.me 我不知道你的地图是什么。它是ItemSet*,那么就不需要了。如果它是一些基类指针类型,那么您应该正确地将其转换为正确的返回类型。这是 C++。避免使用 C 风格的转换作为一种做法。我假设您的地图如我的示例中的迭代器 decl 所示,我拉了它。希望是对的。
猜你喜欢
  • 1970-01-01
  • 2015-07-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-04-07
  • 2017-12-08
  • 1970-01-01
相关资源
最近更新 更多