【问题标题】:Question about const member functions in c++c++中关于const成员函数的问题
【发布时间】:2020-04-02 22:11:55
【问题描述】:

谁能解释一下这个错误? 代码如下:

class O{
    unsigned x;
    unsigned y;
    public:
        O(unsigned x_ ,unsigned  y_): x(x_), y(y_){
        };
        O& operator+= ( O & object){
            x += object.x;
        }
};

class A {
    O item;
    public:
        A(O i): item(i){;
        }
        void fun() const{
            O j(2,3);
            j += item;
        }
};

int main(){
    return 0;
}

当我尝试编译时出现此错误:

In member function 'void A::fun() const':
[Error] no match for 'operator+=' (operand types are 'O' and 'const O')
[Note] candidate is:
[Note] O& O::operator+=(O&)
[Note] no known conversion for argument 1 from 'const O' to 'O&'

谁能解释一下?如果我将 const 限定符添加到 += 运算符的参数,它会编译。所以我认为问题在于我在 const 函数 fun() 内将 item 的引用传递给 += 运算符,它是非 const。谁能解释我为什么这是非法的,以及我如何避免犯这种错误,例如在使用 const 限定符等时有一些经验法则可以遵循?

【问题讨论】:

  • 在 const 限定函数 (void fun() const) 内部,每个类字段都被视为 const。非 const 引用不能绑定到 const 事物。
  • 在 const 方法中调用 j += item 会使 item 成为常​​量,因此需要实现采用 const 引用的运算符。

标签: c++ class reference constants const-reference


【解决方案1】:

在许多地方,const 关键字是一个承诺,即 [某些代码] 不会更改标记为 const 的事物的状态。相比之下,缺少关键字必须被解释为意味着[某些代码]可能改变该事物的状态。

编译器检查这些promise是否一致,如果不一致则报错。

在这种情况下,您有一个声明

O& O::operator+= (O & object);

承诺保持参数object 不变的地方。并且因为这是一个参考参数,所以您不承诺将所参考的内容单独留下。

但是您尝试从上下文中调用该操作

void A::fun() const;

确实承诺保持调用对象的状态不变,然后使用其中一个成员 (A::item) 作为 O::operator+ 的参数。

编译器抱怨您在一个地方承诺保持A::item 不变,而在另一个地方却没有做出这样的保证。

因为O::operator+= 实际上并没有改变它的参数,你可以通过将签名更改为来解决这个问题

O& O::operator+= (const O & object);

完成并除尘。

【讨论】:

  • 这个过程是为了避免无意中修改类成员,对吧?在我看来,由 const 限定符引起的错误不仅仅是没有它的“看不见的错误”..
  • 防止错误是一个很好的理由,但它可以实现代码的编译器优化。
【解决方案2】:

这个成员函数

  void fun() const{
        O j(2,3);
        j += item;
    }

是一个常量成员函数。因此,调用函数的对象的成员被认为是常量成员,特别是在这种情况下,数据成员项被认为是像声明的那样

const O item;

在这个表达式中

j += item;

使用了成员函数

    O& operator+= ( O & object){
        x += object.x;
    }

接受对 O 类型对象的非常量引用。因此,实际上您正在尝试将非常量引用绑定到常量对象。所以编译器会报错。

上述运算符的参数应使用限定符 const 声明,并具有 return 语句,例如

    O& operator+= ( const O & object) {
        x += object.x;
        return *this;
    }

【讨论】:

  • 是的,我忘记退货了。既然我们在这里,我会问另一个严格相关的问题。为什么我不能用对 const 的引用来初始化普通引用?您不能将普通引用绑定到 const 对象,因为您可以对其进行修改,但我看不出这种推理如何扩展到两个引用。
  • @Peanojr 使用非常量引用,您可以更改 const 引用所引用的对象。这将调用未定义的行为。
  • 所以这就像我间接允许通过将 const 引用分配给非 const 引用来更改 const 引用指向的对象?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-12-02
  • 2011-03-23
  • 2020-01-30
  • 1970-01-01
  • 1970-01-01
  • 2010-10-08
相关资源
最近更新 更多