C++ getting round const
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.
Depending on what exactly they were asking for the keywords for you to research are "const_cast" and "mutable".
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.
This can also be done with aliasing, where multiple pointers/references point to a single object:
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.
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.
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.
You can also do this (not that you should) :)
class Foo{private: int stuff;public: void Bar() const { ((Foo*) this)->stuff = 5; }};
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.
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
Popular Topics
Advertisement