这篇文章似乎涵盖了很多基础知识,但作者仍然对返回指针的函数的 const 和非常量重载有疑问。文章的最后一行是:
许多人可能会回答“这要看情况”。但我想问“这取决于什么?”
绝对准确地说,这取决于 A 对象指针对象的状态在逻辑上是否是 A 对象状态的一部分this
object.
举个例子,vector<int>::operator[]
返回对 int 的引用。 int 引用数是向量的“一部分”,尽管它实际上不是数据成员。因此,常量重载惯用语适用:更改一个元素,您就更改了向量。
对于不是这样的示例,请考虑shared_ptr
。这个有成员函数T * operator->() const;
,因为有一个 const 是有逻辑意义的智能指针到一个非常数object。引用对象不是智能指针的一部分:修改它不会更改智能指针。因此,是否可以“重新设置”智能指针以引用不同的对象的问题与引用对象是否为 const 无关。
我认为我无法提供任何完整的指导方针来让您决定受指点在逻辑上是否是对象的一部分。但是,如果修改被指向者会更改任何成员函数的返回值或其他行为this
,特别是如果受指点参与operator==
,那么它很可能是逻辑上的一部分this
object.
我宁愿假设它is部分(并提供重载)。然后,如果出现编译器抱怨我正在尝试修改从 const 对象返回的 A 对象的情况,我会考虑我是否真的应该这样做,如果是这样,请更改设计,以便只有指向 A 的指针从概念上讲,它是对象状态的一部分,而不是 A 本身。这当然需要确保修改 A 不会做任何破坏预期行为的事情this
常量对象。
如果您要发布接口,您可能必须提前弄清楚这一点,但实际上,从 const 重载返回到 const 函数返回非 const 指针不太可能破坏客户端代码。不管怎样,当您发布一个接口时,您希望已经使用过它一点,并且可能对对象的状态真正包含的内容有所了解。
顺便说一句,我也尝试犯错误,不提供指针/引用访问器,尤其是可修改的访问器。这确实是一个单独的问题(德墨忒尔定律等),但是您可以替换的次数越多:
A *getA();
const A *getA() const;
with:
A getA() const; // or const A &getA() const; to avoid a copy
void setA(const A &a);
您担心这个问题的次数就越少。当然后者也有其自身的局限性。