在函数声明的末尾使用"const"是什么意思?

762
我买了一本书,上面写着这样的内容:
class Foo 
{
public:
    int Bar(int random_arg) const
    {
        // code
    }
};

这是什么意思?

33
它将this的类型从Foo* const更改为const Foo* const,这会产生后果。 - sbi
那么答案是否定的。你为什么会认为它是呢? - Janick Bernet
8
@aPoC函数(或者这里的方法)只存在于“内存”中一次(无论它们是static还是非static)。它们会传递一个隐藏的参数this,该参数是指向调用实例的指针。 - ereOn
@sbi 我认为应该是“从Foo*转换为const Foo*”。this不是一个常量指针。过去,一些实现使用常量指针作为技巧来表示this,但我认为这个答案解释得很好。 - starriet
@starriet:啊,**this** 是一个右值,但不是 **const**,对吧?所以我的评论在技术上是错误的,但可悲的是,我不能再修正它了。 - sbi
显示剩余3条评论
6个回答

1244
一个“const函数”,在函数声明之后用关键字const表示,使得这个类函数改变类的数据成员时会产生编译错误。然而,在函数内部读取类变量是可以的,但在这个函数内部写入将会生成编译错误。
另一种思考这样的“const函数”的方式是将类函数视为一个隐式的this指针的普通函数。所以一个方法int Foo::Bar(int random_arg)(末尾没有const)会导致一个函数int Foo_Bar(Foo* this, int random_arg),而调用Foo f; f.Bar(4)将在内部对应于类似Foo f; Foo_Bar(&f, 4)的东西。现在在末尾添加const(int Foo::Bar(int random_arg) const)可以被理解为具有const this指针的声明:int Foo_Bar(const Foo* this, int random_arg)。由于这种情况下this的类型是const,所以不能修改数据成员。
可以解除“const函数”的限制,允许函数写入类的任何变量。为了在将函数标记为“const函数”时允许某些变量可写,这些类变量会用关键字“mutable”进行标记。因此,如果一个类变量被标记为可变的,并且一个“const函数”对该变量进行写操作,那么代码将能够编译通过,并且该变量是可以改变的。(C++11)
通常情况下,在处理“const”关键字时,将const关键字的位置改变在C++语句中具有完全不同的含义。上述使用的“const”仅适用于在括号后面添加“const”到函数声明的末尾。
“const”是C++中一个被过度使用的修饰符:与指针结合时,语法和顺序通常并不直观。关于“const”正确性和“const”关键字的一些阅读材料: Const正确性

C++ 'const'声明:为什么和如何使用


7
如果你喜欢可变的话,你可能会喜欢这个。 "可变" 最常见的用法是作为修改类实例访问控制的互斥锁的修饰符。即使你承诺不修改实例,也不能保证你从中读取的内容不会被持有非 const 引用的其他人修改。 - Dmitry Rubanovich
3
@Janick,我已经自学C++一两年了,从来没有看到过任何书籍涵盖这样的解释,我觉得它非常有帮助。我应该读什么类型的书来学习这些东西,比如这个隐式this指针。 - Steven
5
@Steven:我认为最有帮助的事情可能是实际阅读一本C语言书籍,并了解如何在纯C中实现一些类似面向对象的东西。通过这样做,可以更容易地看到C++本地的面向对象功能如何映射到C中更低级别的构造,最终映射到机器上。 - Janick Bernet
2
还有两个重要的注意点:1)静态数据成员仍然可以被修改。2)这里检查了位常量性,这意味着调用函数的对象的内存逐位进行检查,不应该对其进行任何更改。这进一步告诉我们,如果有一个int*数据成员,则此指针包含在对象内存中的地址不能更改,但是该位置上的值(它不是对象内存的一部分)可以更改。 - Sukrit Gupta
2
@LukasThiersch,如果const函数调用非const函数来更改值,则编译器会抛出错误。 - Eswaran Pandi
显示剩余3条评论

72

考虑两个类类型的变量:

class Boo { ... };

Boo b0;       // mutable object
const Boo b1; // non-mutable object

现在您可以在b0上调用任何Boo成员函数,但只能在b1上调用const限定的成员函数。


21

Bar保证不会改变其被调用的对象。例如,有关const正确性的部分,请参见C++ FAQ中的相关章节


12
不要忘记 mutable 关键字。 - Nikolai Fetissov

14

类似于这个问题。

本质上,它意味着方法Bar不会修改Foo的非mutable成员变量。


10

我总是觉得,从概念上来看,把“this”指针设置为const更容易理解(这基本上就是它的作用)。


10
实际上,不是this指针本身是const,而是它所指向的内容,即*this ;) - fredoverflow

9

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接