Constness of returned object (s) from const member function
What is a good rule of thumb as to whether or not the return value of a constant member function should be const or not? Here is what I am doing, but I am struggling with ambiguous scenarios.
class foo
{
public:
// if the returned object is conceptually
// (and therefore usually literally but not even necessarily)
// owned by *this*,
// then a const ptr should be returned
const ownedByFoo *getOwnedByFoo() const { return m_ownedByFoo; }
ownedByFoo *getOwnedByFoo() { return m_ownedByFoo; }
// what a poor boy to do here?
// veryRelatedToFoo might be a conceptual contemporary or parent
// of Foo. Note naming the function "find..." instead of "get.."
// since *get* implies the object holds it as a data member but
// that may not even be the case here. There could be a
// standalone container that associates foo and veryRelatedToFoo.
// Should constness be symmetrical here?
const veryRelatedToFoo *findVeryRelatedToFoo() const;
veryRelatedToFoo *findVeryRelatedToFoo();
// If the returned object is only (conceptually)
// peripherally related to *this*,
// the returned object probably shoudn't be const, even if
// foo happens to have one of these as a direct data member,
// since we don't want to give away the implementation details of
// Foo and it may hold peripherallyRelatedToFoo simply for performance
// reasons, etc.
peripherallyRelatedToFoo *findPeripherallyRelatedToFoo() const
...
};
Another note is that once you have an asymmetric constant, you can ask const A to return B, then ask B to return A, and then you managed to get around the supposed constant of A.
a source to share
Having a constant of some kind is more than you will find in many languages!
Once you understand (as you do) the difference between "physically const" and "logically const", then the "ambiguous" scenarios are still negotiable. Consider, for example, the fact that a keyword exists mutable
.
I think that you have the right general idea: why is it all controversial and subjective and varies depending on the specific problem and restrictions, etc.
I prefer "exceptions to the rule", so I would not return a non-const pointer from a const method; but I guess I can imagine some scenarios in which I might be tempted ... although I might rather make the way non-const instead.
a source to share
(I ignore the fact that you are returning the state of an object directly like this, which is usually bad because it breaks encapsulation - I see this as "sample code")
There is no connection between them. A const
member function is a member that does not modify the underlying object "at runtime". There are no promises or requirements for the return value to be const
or not. The contract is const
-ness "over" as soon as the method returns. I think you are confused because you are trying to wire the return value using the method that created it.
The return value should const
or should not const
depend solely on the nature of the return value and the semantics you want to assign to this method.
In your specific first case, the two methods should return the same const
-ness. Constant overloading is probably not what you want to use. If you want two options, I would probably make it explicit, like this:
const ownedByFoo *getOwnedByFoo() const { return m_ownedByFoo; }
ownedByFoo *getOwnedByFooForEdit() { return m_ownedByFoo; }
Thus, there is no ambiguity and mysterious connection between the two. Note that I made the second non-const one because we probably don't want the client code to change m_ownedByFoo for the const object. This requirement stems from the semantics of the method ("returns internal state"), not from the relationship between the const
-ness method and the const
-ness return value. If the return value was not part of the object's state, I would probably do something else.
a source to share