6

I have a back up copy of data that I would like to protect so I made it const. I need to violate that constness on two occassions, once to store virgin data to it:

fgBlocks.CopyInto((BlkArray&)backUpCopy); 

w.r.t.

result CopyInto(BlkArray &replica) const {/**/} 

and again when I call RemoveAll() on it which is a non-const method:

((BlkArray)backUpCopy).RemoveAll(true); 

Is the first cast (shown above, (BlkArray&)) correct? It's the one aspect of indirection I haven't cast to before now. Then again I'll add another unused aspect, that of casting away constness for calling an object's methods, which the compiler isn't accepting as shown above.

The members are declared like this:

BlkArray fgBlocks; const BlkArray backUpCopy; 

I'm trying to extend Correa's solution so have:

 BlkArray *pBUCopy = (BlkArray *)&backUpCopy; fgBlocks.CopyInto(*pBUCopy); 

Only problem now is the compiler is failing due to

uninitialized member 'MyClass::backUpCopy' with 'const' type 'const BlockArray'

1
  • Better to use const_cast rather than C-style casts. Makes it more obvious to the reader than constness is being cast away. Commented Feb 28, 2012 at 0:53

3 Answers 3

9

Be aware that if you do this and the object really is const, then modifying it after casting away the constness is undefined behaviour.

fgBlocks.CopyInto(const_cast<BlkArray&>(backUpCopy)); 

Same thing for the other one:

const_cast<BlkArray&>(backUpCopy).RemoveAll(true); 
Sign up to request clarification or add additional context in comments.

11 Comments

The object really is const. Apart from the above calls, I made it a const member and is only otherwise used in a read-only capacity. The call to RemoveAll comes in the destructor of the containing class.
@John unfortunately you can't do what I posted then without causing UB. What you may want to do is make the real variable private and not const, then make a const reference to it public. This way, the class it is a member of can modify it, but the outside world can only look at it through the const reference and so cannot change it.
@John: Why do you need to call RemoveAll? Just let BlkArray's destructor deal with removing the data.
@John so you, the implementor, are trying to protect yourself from the implementation?
@John: An interface (declaration) should not tell you something about the implementation details (definition).
|
1

There is a little trick I learned looking at Qt's internals:

MyClass:circunventConst() const { MyClass* that = const_cast<MyClass*>(this); that->myProtectedVariable = value; } 

7 Comments

That's a few more lines than I'd hoped but seems right for me, thanks, I'll give that a go.
This doesn't help at all (if, as the poster said, myProtectedVariable is const, it is const whether or not *this is const). Also, this causes undefined behaviour if *this is really a const object. Qt is <strike>stupid</strike> silly for doing this.
Well, I'm talking from memory, so can't give specifics why it was done or if it's still in Qt's code. But it sure was the first time I saw that. Of course, for this simple example, the proper way would be myProtectedVariable to be mutable so it would be valid for a const method to change it. It maybe that they saw bugs in compilers with mutable and were working around it, but then I'm just expeculating.
@SethCarnegie: Thanks man! I'll just give it a really <strike>stupid</strike> obscure name to keep it safe.
@John not only pointers, but references too. And your second sentence is almost but not quite correct: it can make a pointer or reference to an object that is declared const not const perfectly fine; the bad thing happens when you modify the object that was declared const through the non-const pointer or reference you got from using const_cast to cast away the const-ness. Then is when you get UB. The way to think of it is that const_cast casts away the const-ness of the type of the reference, but it doesn't actually make the underlying object non-const.
|
0

You can circumvent this problem by simply marking all methods as const, except RemoveAll and CopyFrom, the latter being made to be a method of BlkArray that either implements the logic or passes *this to CopyInto.

To be more secure about who can clear the data / copy new stuff into it, you may make those methods private and declare the necessary classes as friends, or use the passkey pattern to protect those two methods.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.