Mutable Class Members
An introduction to the mutable
keyword, which gives us more flexibility when working with const
objects.
In the introductory course, we covered the const
keyword, and the importance of "const correctness"
One example is the ability to mark class methods as const
if they do not change any data members.
class Character {
public:
int GetHealth() const {
return Health;
}
private:
int Health{100};
};
This serves two purposes:
- It's documentation to other developers - "calling this method won't change the object"
- It's a compiler directive, ensuring that if the method does try to change the object an error is thrown. This includes indirect actions that may modify the object, such as our method calling another method that isn't
const
, or passing our object by reference to a function that hasn't marked the parameter asconst
Constants and const
-Correctness
Learn the intricacies of using const
and how to apply it in different contexts
Why we need Mutable Variables
There are some scenarios where we want certain variables to be changeable (or "mutable") by const
methods.
Typically, these are private variables whose value has no noticeable, outward-facing effect. In the following example, we want to keep track of how many times our object's Health
value was accessed:
class Character {
public:
int GetHealth() const {
++HealthRequests;
return Health;
}
private:
int Health{100};
int HealthRequests{0};
};
Naturally, the compiler won't allow this:
'HealthRequests' cannot be modified because it is being accessed through a const object
We could get around this simply by removing the const
specifier, but that's not ideal.
- The function not being marked as
const
is misleading to any code using our class. Whilst it is changing a data member, the variable it's changing is completely inaccessible and has no visible effect. So, from the perspective of the outside world, the function really should beconst
- Removing
const
specifier has knock-on effects that can reverberate through our code base. For example, any code trying to callGetHealth()
on a const reference to this object will now also throw errors. - The compiler is no longer ensuring this function doesn't change the class in more meaningful ways.
The mutable
Keyword
To solve these problems, we have access to the mutable
keyword.
Any data member marked as mutable
can be freely changed by const
methods:
class Character {
public:
int GetHealth() const {
++HealthRequests;
return Health;
}
private:
int Health{100};
mutable int HealthRequests{0};
};
Of course, to ensure our const
specifier remains meaningful, mutable
should be used sparingly. It's intended only for variables that, if changed, will not affect the object in any way that outside consumers will notice.
In other words, the meaning of const
methods should only have a subtle shift - from "this won't change the object" to "this won't change the object in any way you'll notice"
Summary
In this lesson, we explored the mutable
keyword, learning how it allows for the modification of class member variables within const
member functions.
Main Points Learned
- The
const
keyword lets us maintain"const correctness" by preventing modification of data members in const methods. - The
mutable
keyword enables certain class members to be modified byconst
methods, useful for variables that don't affect the external state of the object. mutable
is intended for use cases where modifying a data member does not change the observable behavior of the object, such as logging or caching.- Proper use of
mutable
requires careful consideration to ensure it does not compromise the design principles of your class or undermine the value and meaning ofconst
keyword.
Multiple Inheritance and Virtual Base Classes
A guide to multiple inheritance in C++, including its common problems and how to solve them