C++ getting round const

Started by
10 comments, last by Will F 17 years, 9 months ago
Hi, I had a phone interview the other day and there was a question that was something like 'if I have a const function, in which I obviously can't change any data, how do I get around this and change non-const data?' I'd never heard of this and it isn't in my teach yourself C++ in 21 days book. The answer was to use something but I can't remember it's name.... it began with mute.... i think. Can anyone tell me what this is? Thanks.
Advertisement
Depending on what exactly they were asking for the keywords for you to research are "const_cast" and "mutable".
-Mike
A good example of when you might need a mutable variable would be if a class had a reference count, an integer that stores the number of other parts of code that currently need the object to exist. One part of code might only need to read values from an object of this class, but it still has to say that it references this object (to prevent the object from getting destroyed by clean-up code elsewhere, for example). So you have an AddReference() member function, that increments the reference count by one. But if the code only has access to a const reference or pointer, then you can't call a non-const member function. If you make the AddReference() function a const member function then you can't manipulate the reference count, because it's part of a const object. But if you make the reference count variable mutable, then you can change that one variable even in a const member function, while the rest of the object remains const.
"We should have a great fewer disputes in the world if words were taken for what they are, the signs of our ideas only, and not for things themselves." - John Locke
I'd much rather hire a programmer who didn't know how to do that ;-)
In case you were wondering what to put in your next christian game; don't ask me, because I'm an atheist, an infidel, and all in all an antitheist. If that doesn't bother you, visit my site that has all kinds of small utilities and widgets.
This can also be done with aliasing, where multiple pointers/references point to a single object:

void SomeObject::ConstFunction(SomeObject& nonconstobj) const{   nonconstobj.member = value;}SomeObject foo;foo.ConstFunction(foo);


This is a little bit evil, however, and can lead to nasty bugs. It's best to try and avoid creating that kind of situation just to circumvent const (which is a sign of bad design anyways). However, aliasing can remain very useful in other areas and slightly more complicated scenarios.

Wielder of the Sacred Wands
[Work - ArenaNet] [Epoch Language] [Scribblings]

Quote:Original post by Joakim_ar
I'd much rather hire a programmer who didn't know how to do that ;-)


Mutable is a necassary construct when a language allows constant objects. If objects are based on state and behavior and you mark the object as constant then you would expect its state not to change. This means that all members of the object that constitute its state should be constant. What about the the members that do not constitute the state of the object? Should those be constant?

The answer is maybe. Not yes or no. Allow the programmer to have the ability to decide.

Another good example, in addition to a ref counter, of where you want to have mutable members on constant objects is for cached values. If a member function has to make an expensive calculation it would be smart to cache the result as a member variable and only recalculating it when its result has been invalidated.
Another example, if you're familiar with multithreaded programming, would be mutexes. If you want to read values from an object, sometimes they need to be protected with a lock on a mutex in order to ensure other threads don't screw stuff up while you read data. Locking a mutex alters the state of the mutex, but not the state of the object which it is protecting; remember, all you want to do is read information, and guarantee that the data isn't changing while you read it. Thus the mutex object needs to be mutable, so that its state can change while being stored in a const object.
"We should have a great fewer disputes in the world if words were taken for what they are, the signs of our ideas only, and not for things themselves." - John Locke

You can also do this (not that you should) :)

class Foo{private:   int stuff;public:    void Bar() const   {      ((Foo*) this)->stuff = 5;   }};
Joshua Barczak3D Application Research GroupAMD
Quote:Original post by ApochPiQ
This can also be done with aliasing, where multiple pointers/references point to a single object:

void SomeObject::ConstFunction(SomeObject& nonconstobj) const{   nonconstobj.member = value;}SomeObject foo;foo.ConstFunction(foo);


That's not really getting around anything, since you still need a non-const reference. The fact that you have a const member function, or even the fact that you have a member function at all is barely relevant. Except for accessing private members, I guess.

If I were to just give you a const Foo&, you'd be stuck.
"Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it." — Brian W. Kernighan
Quote:Original post by jbarcz1

You can also do this (not that you should) :)

class Foo{private:   int stuff;public:    void Bar() const   {      ((Foo*) this)->stuff = 5;   }};


That's simply using a C-style cast as a const_cast. Yet another symptom of the evilness of C-style casts (they do a variety of different things, and are hard to search for in source code. C++ casts are specific, and as ugly as they ought to be, because they should stand out as a code smell, despite the extra specificity.)

This topic is closed to new replies.

Advertisement