has the ability to specify that certain member functions are const
which means that they don't change the state (data) of the object on which they act. This means that they can act on both const and non-const objects of that class.
Not specifying a member function as const means that the member function can only be invoked for non-const objects which obviously limits its use. So if a member function doesn't change an object's state then it should by definition be const. Rather than think about which member functions are const a developer should really think about which ones should be non-const. From personal experience I can tell you that it is usually very painful to go back and make these changes later since it tends to have a ripple effect on other code. It is much easier to put the consts in the first time.
Then of course there is the question of what it means for an object's state to be changed by a method and whether constness refers to the bitwise representation of an object or to its logical representation. This issue eventually lead to the mutable
keyword being added to the language. A mutable method is one that is allowed to change the bitwise representation of an object but not its logical representation.
has a good discussion of all this in Item 21 of his excellent book EffectiveCeePlusPlus, Second Edition
See also: ConstCorrectness
An alternative is to simply not use Const at all, then you don't have to worry either about Mutable or the ripple effect.
True. One can also make the case that whether an object modifies its state should be its own business. That is what encapsulation is all about. -- MichaelFeathers
I think I am beginning to see what you are getting at. If I may poorly paraphrase someone else, the gist of what you are saying is: "If everyone refused to use const then there would be no more const wars". I need to think about this some more. Interesting thought. -- JamesCrawford
Not really: If you refuse to use const
in your classes (and functions), then none of the people who use your class (/function) can use const.
Because, if they promise not to modify the state of the object they're working with, they'll quickly find that they can't call any of your methods -- because you refuse to make any promises to them. -- JeffGrigg
Apart from protecting yourself against your own errors (which I think is the most interesting use of const), there are two other uses: the compiler writers might be able to use it for optimization (although I don't know if there are any real numbers on that), and EmbeddedSystem
s might have instances that are burned into ROM and so would crash if you attempt to change them. Hmmmm, it just struck me that there's yet another keyword overloading here in CeePlusPlus
. There's const for a variable that says that its value, once set, is fixed forever, and there's const for a method which says that it won't change the state of the instance. -- SteveFreeman
I'd like to point out that const doesn't mean that an object's value is fixed, because there may be a live non-const reference to that object, even within the same context as the const handle. What const means is that some
particular handle to that object cannot modify it (and in CeePlusPlusEleven, it further means (if you intend to use the object with the standard library) that it is safe to access the object simultaneously through other const references, without external synchronization). When added to a member function, const essentially changes the type of this from my_class* const to const my_class* const. If you consider a member function to be isomorphic to a free function with an additional reference/pointer parameter, you see that the const member restriction for const objects is very much in line with the standard function overloading semantics. And then there's const_cast...
I've heard that CeePlusPlus const is not a useful to optimization as you may think -- because the language definition is not strict enough to allow it. -- JeffGrigg
I find it interesting that while JavaLanguage
is based on CeePlusPlus
, it doesn't use const (although it is a reserved keyword) and that every class implicitly derives from the class Object making it possible to pass objects around without knowing their type. -- JamesCrawford
I have always been a big advocate of letting the compiler find errors for you. It seemed obvious to me that the earlier a problem is detected the better. Thus giving the compiler extra information like 'const' and using 'protected' and 'private' on data and methods to prevent unauthorised access are good things to do because it allows the compiler to detect bugs for you. For this reason I have always been a believer in StaticallyTyped
languages. And yet there are people whom I respect who are writing systems in languages such as SmalltalkLanguage
who claim that concepts such as const, access restrictions, StaticTyping
, etc. are a hindrance rather than a help because it makes it much harder to ReFactor
code. In fact, I wonder if statically typed languages and constructs such as const are more suited for doing WaterFall
development while DynamicallyTyped
languages are more suited for IterativeDevelopment
Maybe what's needed are editing tools that allow you to ReFactor
code written in StaticallyTyped
languages more easily. For instance if I try to use a non-const method on a const object, a browsing editor could let me know about it and might even offer to automatically change it to const if that were possible. Seems like you could get the best of both worlds that way.
I use CeePlusPlus (and const) and I refactor.
I haven't found const to inhibit refactoring. In fact, as const declarations act effectively as multiple UnitTest
s executed by the compiler, I find that it helps refactoring.
C++ is a StaticallyTyped
language, with support for strong compile-time checking. "const" is just one part of StaticTyping
; part of the GrainOfTheLanguage
. -- JeffGrigg
I'm firmly in the const-camp. Const is as much for the reader as for the compiler: When I deal with a const & parameter, I promise not to change its logical state, and the compiler merely enforces my promise. Whether an object changes its physical state when I call its methods is not my concern.
is only a problem when it's not applied consistently from the start, but the same can be said for encapsulation :) -- BurkhardKloss