C++ methods allow a const
qualifier to indicate that the object is not changed by the method. But what does that mean? Eg. if the instance variables are pointer
What can a 'const' method change?
Without explicitly casting away constness, a const
method can change:
mutable
data members, andconst
access to, irrespective of whether that data's accessible:
For members of class
/struct
/union
type, it relies on the constness of their member functions to determine which operations should be allowed. (It can also change any non-const local variables and by-value parameters, but I know that's not what you're interested in).
It can call other const
methods which will have these same abilities and restrictions.
Eg. if the instance variables are pointers, does it mean that the pointers are not changed, or also that the memory to which they point is not changed?
It means the pointers can't be (easily/accidentally) changed. It does not mean that the pointed-to memory can't be changed.
What you've stumbled on is the logical incorrectness of a const
function changing pointed-to or referenced data conceptually owned by the object. As you've found, the compiler doesn't enforce the const
correctness you may want or expect here. That's a bit dangerous, but means constness doesn't need to be explicitly removed for pointers/references to other objects which may be changed as a side-effect of the const
function. For example, a logging object. (Typically, such objects are not logically "owned" by the object whose const
function is operating on them.) The key point is that the compiler can't reliably distinguish the type of logical ownership an object has over pointed-to data, so it's got to guess one way or the other and allow the programmer to either override, or not be protected by const
-ness. C++ forgoes the protection.
Interesting, I've heard Walter Bright's D language flips this default, making pointed-to data const
by default in const
functions. That's seems safer to me, though it's hard to imagine how often one would end up needing to explicitly cast away constness to allow wanted side-effects, and whether that would feel satisfyingly precise or annoyingly verbose.
const
basically prevents changing the class instance members' values inside the function. This is useful for more clearer interface, but pose restrictions when using inheritance for example. It's sometimes a little bit deceiving (or a lot actually), as in the example you posted.
const
would be most appropriate for Get
functions, where it is obvious that the caller is reading a value and has no intentions of changing the object state. In this case you would want to limit the inherited implementations as well to adhere to const
ness, to avoid confusion and hidden bugs when using polymorphism.
For example
class A{
int i;
public:
virtual int GetI() {return i;};
}
class B : public A{
public:
int GetI() { i = i*2; return i;}; // undesirable
}
changing A to:
virtual int GetI() const {return i;};
solves the problem.
const when applied to a method means:
This means that the state
of the object will not be changed by the method.
This means any members that are part of the objects state can not be modified, nor can any functions that are not also const be called.
As this relates to pointers. It means the pointer (if it is part of the state) can not be changed. But the object the pointer points at is part of another object so that means you can call non cost methods on this object (as it is not part of the state of this object).
There are two aspects to this question:
const
mean to the compiler?const
apply when it cannot be validated by the compiler?The first is rather simple. The compiler validates that no data members are modified (unless they are qualified as mutable
). It validates this recursively: for any user-defined types, it checks that no non-const methods are invoked. For built-in types, it validates that they are not assigned.
The transformation for pointers is T*
to T*const
(const pointer), not const T*
(pointer to const). This means that the compiler does not validate that the object pointed to is not modified. Obviously, this leads to question 2.
How does const
apply when not validate by the compiler? It means whatever it should mean to your application. This is usually referred to as logical const. When to use const
with respect to logical const-ness is subject to debate.
Most succinctly, it means that the type of this
is const T *
inside const member functions, where T
is your class, while in unqualified functions it is T *
.
Your method set
does not change data
, so it can be qualified as const. In other words, myclass::data
is accessed as this->data
and is of type int * const
.