常量成员函数

9

阅读了这篇文章后,我理解声明一个方法为const可以防止它意外修改类的成员变量。

  • const方法常用吗?
  • 所有不应修改成员变量的方法都应该使用const吗?
8个回答

14

是的,当合适时应该始终使用const

它能让你的编译器免费为你检查应用逻辑,静态地断言const正确性

有些人甚至说,const应该是默认值,非常量才需要使用mutable


1
此外,您可以仅在函数的“const”限定符上重载函数。例如,如果将对象声明为“const”,则允许索引运算符以只读方式自动返回元素。 [*尽管如此,“只读”仍然仅适用于编译时。在运行时,“const”无法做任何事情] - Mephane
我在思考你的声明“const 作为默认值,非常量使用 mutable”。这似乎是一个极端的立场,但我会尝试感受一下我的想法。 - Stephane Rolland
1
@Stephane:我会“引导”你的思考-> 当你读取或写入对象时,你可能会出错吗? - Matthieu M.
@Matthieu,所以您会对经常编写/更改的对象的类成员进行const-fullprotect吗? - Stephane Rolland
@Stephane:不是的,但每个单独的“只读”方法都标记为“const”。然而问题在于,如果非const方法是只读的,则编译器不会给出任何提示。如果const方法尝试写入,则会出现错误。为了强制执行const正确性,最好指定何时需要写访问权限,而不是默认授予它。 - Matthieu M.
我完全同意对于只读方法,我已经在使用 const 保护进行编写。Peoro 所添加的是一个更极端的观点(就我理解而言):甚至有人说类应该尽可能地定义为具有 const 成员,并仅声明可变字段。在我考虑它是否滥用 constness 之前,我必须先试验一下;-) - Stephane Rolland

6
我在设计中广泛使用const来传达意图。如果我打算让一个方法成为一个纯查询而不是修改函数,我会在签名中强制执行并用'const'来传达这一点。
我鼓励您查看Meyer关于无副作用函数的思考以及其对测试能力的影响。

4

这是我的亲身经历。

几年前,我一直反对使用const,只是因为在设计和编写更长的函数签名时有所限制等等...

但我的一个项目领导者总是坚持不懈地提醒我:“你应该使用const函数,它可以避免意外和无意义的操作。”

有一天,我面临着一个难以解决的bug。日复一日,夜复一夜......简直是一场噩梦。设计对我来说太大了,我无法完全掌握它。我白费力气地搜索,最终决定我已经迷失了。

然后我花了两天时间重新定义所有应该是const的函数。我的意思是,两天时间。(重新编译需要很长时间,因为这是一个500万行代码的项目。)

然后:我找到了那个bug......或者说是编译器帮我找到了那个bug:在一个类似getter的方法中,本应该给我一个GUI控件的首选大小,但实际上代码计算了大小,同时还缓存了大小并更新了大小......从而修改了对象。

现在,有时候我会忘记加const。但如果我注意到了,我就会改正它。


1

const添加到成员函数中,允许在常量引用对象上调用它,因为它保证实例变量不会被更改。在STL的各个地方都存在常量引用,因此,在函数不打算修改对象状态的情况下,将成员函数标记为const是有意义的。

注意:可以将某些实例变量标记为mutable,以便即使在const函数中也可以更改它们。例如,这对于实现查找缓存非常有用。


1

声明一个不应修改成员变量的方法:

  1. 确保你认为发生的事情就是正在发生的事情,即你不会意外地修改某个变量。
  2. 向函数的调用者声明该方法不会修改成员变量,消除了阅读代码或依赖说明文档的需要。

因此,在任何有意义的地方都要使用 const。尽管如此,它们并没有被广泛使用,很可能是因为大多数开发人员没有看到巨大的好处。


1

如果您忘记将访问器标记为const,编译器将不允许在const对象或对const对象的引用上调用该方法。因此,标记访问器为const确实很重要。


是的,我知道当人们忘记将 getter 声明为 const 时会感到痛苦。我们现在必须使用一个完全忽略了这个概念并将每个成员函数(包括 getter)都定义为非 const 的框架。现在,我们不得不将指针/引用作为非 const 传递,无论我们是否肯定只想读取该对象... -_- - Mephane

1
如果您有一个常量引用或指针(即指向const的指针)的类对象,那么您只能调用该类的const成员方法。
因此,如果某人“忘记”将“获取”方法设置为const,则无法使用const引用来调用它(虽然可以使用const_cast进行解决,但我们不想使用这种方式!)。
所以,是的,如果该类不会被该方法修改,那么它应该是const的。
请注意:有一些情况下,您确实希望将变量作为“实现细节”进行修改,例如惰性加载或锁定互斥。在这种情况下,您仍然可以使方法为const,但使该成员变量“可变”。
如果您正在编写虚拟方法,并且没有派生类需要将其设置为可变,则应将其设置为const。

1

尽可能使用const关键字。

它可以防止代码中的错误。

它大大提高了代码的可读性。 每个阅读头文件并看到const关键字的人都可以立即理解const方法不会改变对象的状态,并且可以在不担心更改对象的情况下使用,例如。


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