在非常量函数中使用const_iterator

时间:2012-09-27 15:50:32

标签: c++ stl iterator

我的程序结构类似于:

class A {
    private:
        std::set<B> members;
    public:
        void func(const C& arg) {
            std::set<B>::iterator iter = members.find(a);
            if(iter != members.end()) {
                iter->check(arg);
            }
        }
}



class B {
    private:
        std::deque<C> writers;
    public:
        void check(const C& arg) {
            if(std::find(writers.begin(), writers.end, arg) != writers.end()) {
                /* Code */
            }
        }
}


class C {
  private:
      int id;
  public:
      bool operator==(const C& arg) {
          return arg.id == this->id;
      }
}

编译时,我收到以下错误消息:

no matching function for call to ‘B::check(const C&) const’  
note: candidates are: void B::check(const C&) <near match>

如果我将check()声明为const,则编译器会抛出一个错误,要求将C类中的重载运算符==声明为const。我不知道将重载运算符设为const是否正确。 (我尝试了一次,据我所知,它也有一些错误)。

我一直试图解决这个问题超过五天,仍然没有任何线索。

3 个答案:

答案 0 :(得分:3)

首先,operator== const。除非您想要混淆用户,否则它不会修改数据,也不会修改数据。通常,每个不需要修改对象状态的函数都应该是const,以便提供最大的灵活性(即允许通过常量引用进行调用)。

同样可以应用于B::check,如果它只测试而不是修改,那么它应该是const。并且在A::func中进行扩展,如果它不需要修改那么它应该是const。

错误消息在不同的编译器中会略有不同。在您的情况下,编译器执行了重载解析,并且找不到与其抱怨的调用匹配:

  

没有用于调用'B :: check(const C&amp;)const'的匹配函数   注意:候选人是:void B :: check(const C&amp;)

这表示它看到了您的成员但丢弃了它,因为它需要具有const标记的成员函数。在其他编译器中,错误消息将包含以下行:调用void B::check(const C&)丢弃限定符这有点复杂并试图说在const上调用非const成员函数引用将需要忽略const限定符。

答案 1 :(得分:3)

您肯定会将B::check()C::operator==声明为const,因为它们不会更改对象状态中的任何内容。

它也可能不那么明显,但std::set<B>::iterator实际上是const_iterator(假设你使用的是C ++ 11编译器)!因此,您无法通过B迭代器从set对象调用任何非const函数成员。

答案 2 :(得分:-1)

请记住,当有可能时,您应该更喜欢非const版本。至少这是斯科特·梅伯所说的。

这是一个长时间的讨论:

Should I prefer iterators over const_iterators?