tags:

views:

173

answers:

6

In light of the accepted answer pointing out that returning a non-const reference to a member from a const instance method won't compile (without a cast or making the member variable mutable), the question has become more a general best-practices discussion of const instance methods.

For posterity, here's the original question:

If I have an object with a getter that returns a non-const reference, for example:

SomeObject& SomeOtherObject::foo(){
   return someObjectInstance;
}

Should this be made const? Obviously the call itself doesn't modify the object, but the caller could then modify someObjectInstance which would mutate my instance of SomeOtherObject.

I guess my question really boils down to "what exactly does const on a member method mean?" Is it A) the call itself won't mutate the object or B) no mutation of the object can occur during the call, or as a result of the returned references/pointers (with a caveat for people who do const_casts).

As an aside, I'm currently adding this where I need const calls.

 const SomeObject& SomeOtherObject::constFoo() const{
   return someObjectInstance;
}

to be on the safe side, since I'm reluctant to do

 SomeObject& SomeOtherObject::foo() const{
   return someObjectInstance;
}

even though it would make my life easier in some places.

+2  A: 

To answer your question:

"what exactly does const on a member method mean?"

It means that the method can safely and sensibly be applied to a const object. Of course, what "safely" and "sensibly" mean will depend on the problem domain your classes model.

You might also want to consider having your accessors return values, rather than references. If they must return references, then I would reconsider my overall design.

anon
A: 

"what exactly does const on a member method mean?"

It means that the method does not alter member variables of a particular class. Also, using const does not allow the method to call another non-const method.

It is used for readability and clarity, as well as the safety nature of it, for accidental alterations, either directly, or by calling another method that may.

Sev
A: 

The semantics of const depend on the problem domain. If it's potentially ambiguous, document it.

For example, if you have a class that is wrapping access to a database, it would be perfectly sensible to have "const" methods be those that do not change the state of the database, even if they might change some of the hidden internal state of the object (using the 'mutable' keyword to allow this).

Tyler McHenry
+3  A: 

const (when applied to a member function) is mainly useful as a means of self documenation. It is a contract with the calling code that this function will not modify the external state (i.e. have no observable side effects).

The compilier achieves this by making all members effectively const while inside a const member function

It is not uncommon to see code like:

const SomeObject& SomeOtherObject::constFoo() const;
SomeObject& SomeOtherObject::constFoo();

The following won't compile (MSVC 9 and gcc 3.4.4)

SomeObject& SomeOtherObject::constFoo() const{
  return someObjectInstance;
}

You could hack around the above error by casting away the const:

SomeObject& SomeOtherObject::constFoo() const{
  return (SomeObject&)someObjectInstance;
}

but this of course breaks the contract with the users of your code that you won't be changing the SomeOtherObject instance.

You could also make someObjectInstance mutable to be able to avoid the cast, but in the end it really isn't any better.

Dolphin
Interesting, I never actually tried compiling the const version that returns a non-const reference. I just assumed it worked, I guess it makes my questions a bit moot.
patros
ew, use const_cast :)
GMan
casting away const is eww either way, IMO
Dolphin
That will not compile assuming: 'someObjectInstance' is a member of this object :-) <Pedantic> Bill.
Martin York
@patros: moot actually means: worth arguming about. http://uk.encarta.msn.com/dictionary_1861776526/moot.html
Martin York
The widely accepted modern usage is that in this type of context it means obsolete, or already decided. But feel free to argume away.
patros
In fact the #2 definition in that link you posted is "not relevant".
patros
Yep: :-)
Martin York
@Martin York: What won't compile? I specifically pointed out the function that won't compile. The cast (C style or const_cast) both compile just fine with the compilers mentioned.
Dolphin
A: 

what exactly does const on a member method mean?

It means that you promise not to modify any of your non-mutable member data within the function. Said another way, it means the implied this pointer points to a const object.

IMHO, it's poor practice to return non-const references to private member data. It opens the door for a user of your class to modify its internals without going through the public interface.

Kristo
+1  A: 

If you have an object, and call any number of const methods on it in the course of processing, the observable behavior will not change, I'd say.

The Standard (9.3.2, para 2) says "In a const member function, the object for which the function is called is accessed through a const access path; therefore a const member function shall not modify the object and its non-static data members." This also means you can't return a non-const reference or pointer, through the normal const-correctness rules.

(This doesn't mean the internals of the class can't change; the Standard has the mutable keyword to designate member data that can change in a const function.)

David Thornley