C ++中的Const对象,Const成员函数和可变变量

时间:2017-01-25 11:58:43

标签: c++ function const mutable member-functions

我知道const对象无法调用非const成员函数。它在C ++ 14标准(ISO / IEC 14882:2014)第9.3.2节第3段中这样说:

  

只有当object-expression与成员函数一样是cv-qualified或less-cv-qualified时,才能在object-expression(5.2.5)上调用 cv-qualified 成员函数

如果成员函数没有修改任何内容,这个约束是否有意义?或者如果成员函数修改了一个可变变量?例如:

class My_Class {
    public:
        mutable int value;
        void function( int x ) const { value = x; } //     Correct
      //void function( int x )       { value = x; } // Not Correct
        My_Class() : value(0) {}
};

int main(){

    const My_Class obj;
    obj.function( 1 );

    return 0;
}

在这种特定情况下,如果函数是const,则程序是正确的,函数可以修改const对象的变量。如果函数不是const,则程序不正确。所以最后,我需要编写const来修改某些内容,这应该是const的相反目的。

有谁知道为什么这条规则是这样设计的?

3 个答案:

答案 0 :(得分:2)

  

如果成员函数没有修改任何内容,那么[第9.3.2节,第3段]是否有意义?或者如果成员函数修改了一个可变变量?

是的,确实如此。函数的调用者通常不能知道函数是否修改任何非可变成员。它知道函数是否为const,因此编译器只能根据它做出决定。

非const函数可以修改非可变状态,所以你显然不能在const对象上调用它。非const函数是否确实修改状态是无关紧要的,因为它是在决定是否允许调用时不可用的实现细节。换句话说,constness是函数接口的一部分,而函数的实现不是接口的一部分。函数的接口由其声明完全指定。

一个例子:

struct C {
    mutable int a;
            int b;
    void do_something();
};

const C c;
c.do_something();

允许通话do_something是否有意义? do_something可能无法修改b的事实是否会影响到这一点?我们怎么能认为do_something不会修改b

答案是:它没有意义。它没有效果。我们无法做出这样的假设。

编写一个不会修改任何非可变状态的非const成员函数 - 至少可能通过返回非this的非const引用/指针间接地允许或允许这种修改 - 尽管标准允许这样做。

  

所以最后,我需要编写const来修改一些东西,这应该是const的相反目的。

这似乎是矛盾的,但那是因为它过于简单了。您需要编写const才能修改 const对象的可变状态。你编写的const声明你不修改任何非可变状态,并且该声明允许在const对象上调用它。

您的注释掉的非const函数仍然可以与非const对象一起使用。

答案 1 :(得分:2)

你的问题存在根本性的误解:

class My_Class {
    public:
        mutable int value;
        void function( int x )       { value = x; } // Absolutely fine
        My_Class() : value(0) {}
};

mutable并不意味着“只能在const成员函数中进行修改”。这意味着“可以在const成员函数中修改甚至”。

答案 2 :(得分:1)

mutable关键字

  

适用于非引用非const类型的非静态类成员,并指定该成员不影响类的外部可见状态(通常用于互斥,备忘录缓存,延迟评估和访问检测) 。 const类实例的可变成员是可修改的

您质疑C ++关键字的有效性。我觉得这个定义中的例子提供了需要这样一个关键词的正面证据,并且语言设计者想象的mutable对我们来说是一个福音。