Archived

This topic is now archived and is closed to further replies.

zipless

How can a change a const value?

Recommended Posts

OK i''ve never really used const''s before but i''ve decided that i could probably do with using them here and there but i also need to be able to modify their values. i''ll have something like this
  
class Csomeclass
   {
   public:
      const char *pointer;
      void ChangePointer(char *new);
   };
  
But what would i put in the function? /* Ignorance is bliss, then you go and spoil it by learning stuff */

Share this post


Link to post
Share on other sites
A varible constant would make a better oxymoron.

I take it that means that it''s going to be a bit on the impossible side? I''m sure i read something somewhere about being able to change them, damm.



/* Ignorance is bliss, then you go and spoil it by learning stuff */

Share this post


Link to post
Share on other sites
C++ is an extremely flexible language and yes(paradox aside) let you change const data.


  


const int i = 3;

const_cast<int>(i) = 4; //cast away constantness





But your code design is defenitly wrong. Something in those lines is much better (and does not need to cast away constaness)

  


class SomeClass
{
public:
const char* GetPoniter(void) const { return pointer; }

void ChangePointer( char* newPointer );
private:
char* pointer;
};



Since GetPointer is inline, there is no cost associated with using it.

Share this post


Link to post
Share on other sites
You could use const_cast to remove the constantness of a const.
But yeesh, that sort of defeats the purpose of using a const, doesn't it?
From what I've learned, it's not good prgramming practice to use const_cast, but it's there for you.

  
const_cast <type> (expression);


Edited by - Draxis on February 16, 2002 4:54:13 PM

Share this post


Link to post
Share on other sites
Ah, found out another way as well, i''m sure i''d tried using a cast before but i guess i can''t have.

const int var = 56;
int *change = (int *)&var;
(*change) = 34;

I''ll just use that inside the ChangePointer func, cheers guys. I''ll keep the pointer publicas well, mainly becuase i find casting slightly less annoying than using functions to retrieve values.



/* Ignorance is bliss, then you go and spoil it by learning stuff */

Share this post


Link to post
Share on other sites
quote:
Original post by zipless
const int var = 56;
int *change = (int *)&var;
(*change) = 34;



And what happens when the compiler notices you have this nice, const integer and decides to put it into read-only memory? Then your call *changed = 34 will hack up a nasty wet hairball, usually causing the program to crash or become unpredictable.

const_cast and the typical C cast to get rid of const are bad ideas not simply because they enforce good programming behaviours, but also sometimes because const data may not be modifiable, period. You should understand well where that data is going and what''s being done to it before you cast away const.

A better way to appear const, yet safely be able to modify things is with the mutable keyword. From the standard:

quote:

The mutable specifier on a class data member nullifies a const specifier applied to the containing class object and permits modification of the mutable class member even though the rest of the object is const.



Take an example -- we have an operation that is expensive to compute.

  
class Does_Something_Expensive {
private:
int expensive_operation() const ;
public:
int get() const { return expensive_operation(); }
};


We''ve made things const, because we want to be safe and make sure people aren''t mucking with things they shouldn''t. That means normally that we can''t cache the value (within the class) without either removing const''s or casting it away somewhere.

But with mutable, we do this:

  
class Does_Something_Less_Expensive {
private:
int expensive_operation() const;
bool has_changed() const;
public:
int get() const
{
if (has_changed()) {
cached_value = expensive_operation();
}
return cached_value;
}
private:
mutable int cached_value;
};


And now we can cache the value, even in a const object, safely.


---- --- -- -
Blue programmer needs food badly. Blue programmer is about to die!

Share this post


Link to post
Share on other sites
quote:
Original post by zipless
Ah, found out another way as well, i''m sure i''d tried using a cast before but i guess i can''t have.

const int var = 56;
int *change = (int *)&var;
(*change) = 34;

I''ll just use that inside the ChangePointer func, cheers guys.



The code that you''ve written above invokes undefined behaviour. You can cast away the const-ness of an object, but if that object began life as const, and you then change the object, it''s undefined behaviour. If you need to change it, then it''s not constant

quote:

I''ll keep the pointer publicas well, mainly becuase i find casting slightly less annoying than using functions to retrieve values.


If you ever work on large projects requiring good encapsulation, you might realise why this is not a good approach.

--
Very simple ideas lie within the reach only of complex minds.

Share this post


Link to post
Share on other sites
quote:
Original post by mossmoss
And what happens when the compiler notices you have this nice, const integer and decides to put it into read-only memory? Then your call *changed = 34 will hack up a nasty wet hairball, usually causing the program to crash or become unpredictable.


The compiler cannot do this to member variables though. You are allowed to change the value of member constants. If it was truely constant, you would also make it static. But don''t do what you did there zipless; it''ll succeed or fail at runtime depending on compilation options. (Release&Assume-No-Alias->Boom)

  
class CArray
{
public:
CArray(int size) : m_Size(size) {}
protected:
const int m_Size;
};



mutable does not apply to this case. Mutable lets member variable change when the object instance is constant. You cannot declare a variable const and mutable, that is an oxymoron.


The root of the problem is that you are using a char*, there is no correct C++ way to handle the situation due to this. Since it is a primative pointer, and since you allow them to change it, you may as well make it public.

If this is for a utility class, handling errors or some-such-thing, just make the pointer public. If it''s a regular class, change the names of everything to better reflect what''s really happening.

  
class CAvatar
{
public:
const std::string& name(){return m_name;}
void ChangeName(std::string& newName);
void ChangeName(const char* const szNewName);
protected:
std::string m_name;
};


It''s easily conceivable that you would need to do something other than update m_name upon a name change (say send it over the wire to everyone else playing the game).

Share this post


Link to post
Share on other sites
Ah OK, casting the value works in debug config but not in release so that idea's gone out of the window. I had assumed that it would work because there is no ROM it's only a section of memory marked as read only, i thought that accessing it through it's address would by-pass and checking. I assume that if i wanted to i could do it using assembler?

I'll use mutatable and i'll probably end up making the member private as well. For the record the class is going to cache a file from disc into memory, pointed to by char *cache, the end of the file will be pointed to by char *chacheend. I definately don't want these values changing noramlly so i though const's would be a good way to go. I'll need to change cacheend if the file is altered, so thats why i wanted to know.

cheers once again guys.

By the way, was i right, could i have used assembler to change the const value? I'd assume so becouse there would be no checking performed, right?



/* Ignorance is bliss, then you go and spoil it by learning stuff */
EDIT: changed a load of grammer and spelling errors, i need sleep

Edited by - zipless on February 17, 2002 9:09:00 AM

Share this post


Link to post
Share on other sites
quote:
Original post by zipless
By the way, was i right, could i have used assembler to change the const value? I''d assume so becouse there would be no checking performed, right?


If you were hell-bent on changing a const value, sure you could find a way. However, the simple answer is to not declare variables which will change as const. Any other approach just makes life hard for yourself.

--
Very simple ideas lie within the reach only of complex minds.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Just remember that if something is said to invoke undefined behaviour, anything can happen. Even if it worked in release build as well, you were just lucky.

If you have to start playing about with the assembly, then you are writing really non-protable code. You need to ask yourself why you are going to these extremes and find a defined, cross-platform alterative.

Share this post


Link to post
Share on other sites
The code is going to be used with DirectX stuffs so i''m pretty much stuck with one platform anyway so using assembler won''t really make any difference. Don''t get me wrong though, i''m not thinking about using it i just wondered if i could cos i''m about to re-learn some ASM. I''ll use mutatable once i''ve played about with it for a while.

I know that a lot of people might consider changing the value in a memory address dangerous because there is no type checking etc, theres no safety net, but as long as the code is designed well there shouldn''t be any problems.

I can see why using a pointer with the const was a bad idea though, like i said at the start, i''m not familiar with them and i wasn''t sure how the compiler was supposed to react never mind how it would actually react. At least i won''t be making that mistake again.

Share this post


Link to post
Share on other sites