One of the more useful things about const
correctness is that it serves as a way of documenting code, providing certain guarantees to the programmer and other users. These guarantees are enforced by the compiler due to const
ness, with a lack of const
ness in turn indicating that code doesn’t provide them.
const
CV-Qualified Member Functions:const
can be assumed to have intent to read the instance, and:mutable
variables.mutable
variables.const
can be assumed to have intent to modify the instance, and:This can be used to make assumptions about the state of the object after any given member function is called, even without seeing the definition of that function:
// ConstMemberFunctions.h
class ConstMemberFunctions {
int val;
mutable int cache;
mutable bool state_changed;
public:
// Constructor clearly changes logical state. No assumptions necessary.
ConstMemberFunctions(int v = 0);
// We can assume this function doesn't change logical state, and doesn't call
// set_val(). It may or may not call squared_calc() or bad_func().
int calc() const;
// We can assume this function doesn't change logical state, and doesn't call
// set_val(). It may or may not call calc() or bad_func().
int squared_calc() const;
// We can assume this function doesn't change logical state, and doesn't call
// set_val(). It may or may not call calc() or squared_calc().
void bad_func() const;
// We can assume this function changes logical state, and may or may not call
// calc(), squared_calc(), or bad_func().
void set_val(int v);
};
Due to const
rules, these assumptions will in fact be enforced by the compiler.
// ConstMemberFunctions.cpp
ConstMemberFunctions::ConstMemberFunctions(int v /* = 0*/)
: cache(0), val(v), state_changed(true) {}
// Our assumption was correct.
int ConstMemberFunctions::calc() const {
if (state_changed) {
cache = 3 * val;
state_changed = false;
}
return cache;
}
// Our assumption was correct.
int ConstMemberFunctions::squared_calc() const {
return calc() * calc();
}
// Our assumption was incorrect.
// Function fails to compile, due to `this` losing qualifiers.
void ConstMemberFunctions::bad_func() const {
set_val(863);
}
// Our assumption was correct.
void ConstMemberFunctions::set_val(int v) {
if (v != val) {
val = v;
state_changed = true;
}
}
const
Function Parameters:const
can be assumed to have intent to read those parameters, and:const
can be assumed to have intent to modify those parameters, and:This can be used to make assumptions about the state of the parameters after being passed to any given function, even without seeing the definition of that function.