0

我有一个类似于以下结构的程序:

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正确的做法。(我试过一次,据我记得它也给出了一些错误)。

我已经尝试解决这个问题超过五天了,但仍然没有线索。

4

3 回答 3

3

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

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

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

没有匹配函数调用 'B::check(const C&) const'<br> 注意:候选者是:void B::check(const C&)

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

于 2012-09-27T15:54:17.030 回答
3

您绝对应该声明B::check()并且C::operator==因为const它们不会更改对象状态中的任何内容。

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

于 2012-09-27T15:59:20.667 回答
-1

请记住,如果可能,您应该更喜欢非常量版本。至少这是斯科特·梅伯所说的。

这是一个很长的讨论:

我应该更喜欢迭代器而不是 const_iterators 吗?

于 2012-09-27T16:00:33.637 回答