什么时候成员函数应该有const限定符,什么时候不应该?

SCF*_*nch 7 c++ const-correctness

大约六年前,一位名叫Harri Porten的软件工程师写了这篇文章,问了一个问题,"成员函数什么时候应该有const限定符?什么时候不应该?" 我发现这是我能找到的关于这个问题的最好的写作,我最近一直在努力解决这个问题,而且我认为在大多数关于const正确性的讨论中,这个问题都没有得到很好的解释.由于当时不存在像SO这样强大的软件信息共享站点,我想在这里重新提出这个问题.

Ste*_*sop 5

这篇文章似乎涵盖了很多基础,但作者仍然有一个关于返回指针的函数的const和非const重载的问题.文章的最后一行是:

许多人可能会回答"这取决于".但是我想问一下"这取决于什么?"

绝对精确,它取决于A对象指针对象的状态是否在逻辑上是this对象状态的一部分.

对于它的示例,vector<int>::operator[]返回对int的引用.int referand是向量的"一部分",尽管它实际上不是数据成员.所以const-overload惯用法适用:更改元素并且你已经改变了向量.

举个例子,不要考虑shared_ptr.这有成员函数T * operator->() const;,因为具有指向非const 对象的const 智能指针是合乎逻辑的.referand不是智能指针的一部分:修改它不会改变智能指针.因此,您是否可以"重置"智能指针以引用不同对象的问题与参考是否为常量无关.

我不认为我可以提供任何完整的指导方针来让您决定指针对象是否在逻辑上是对象的一部分.但是,如果修改指针对象改变了返回值或任何成员函数的其他行为this,特别是如果指针对象参与其中operator==,则很可能它在逻辑上是this对象的一部分.

我会错误地认为它部分(并提供重载).然后,如果出现一种情况,编译器抱怨我正在尝试修改从const对象返回的A对象,我会考虑是否真的应该这样做,如果这样改变设计,那么只有指针-to-A在概念上是对象状态的一部分,而不是A本身.这当然要求确保修改A不会做任何破坏thisconst对象的预期行为的事情.

如果你要发布接口,你可能需要事先弄明白这一点,但实际上从const重载返回到const-function-returning-non-const-pointer不太可能破坏客户端代码.无论如何,当你发布一个界面时,你希望它有点使用它,并且可能会感觉到你的对象的状态真的包含了什么.

顺便说一句,我也试图在不提供指针/引用访问器方面犯错,尤其是可修改的访问器.这真是一个单独的问题(Demeter法则和所有这些),但你可以替换的次数越多:

A *getA();
const A *getA() const;
Run Code Online (Sandbox Code Playgroud)

有:

A getA() const; // or const A &getA() const; to avoid a copy
void setA(const A &a);
Run Code Online (Sandbox Code Playgroud)

你担心这个问题的次数越少.当然后者有其自身的局限性.