34

I have a legacy function that looks like this:

int Random() const { return var_ ? 4 : 0; } 

and I need to call a function within that legacy code so that it now looks like this:

int Random() const { return var_ ? newCall(4) : 0; } 

The problem is that I'm getting this error:

In member function 'virtual int Random() const': class.cc:145: error: passing 'const int' as 'this' argument of 'int newCall(int)' discards qualifiers 

Now I know in order to fix this error I can make my newCall() a const function. But then I have several funciton calls in newCall() that I have to make, so now I would have to make all of those function calls const. And so on and so forth until eventually I feel like half my program is going to be const.

My question: is there any way to call a function within Random() that isn't const? Or does anyone have any ideas on how to implement newCall() within Random() without making half my program const.

Thanks

-josh

5
  • You could make Random() non-const. Commented Feb 15, 2011 at 19:30
  • I would like to but Random() is legacy code that I can't really touch. Commented Feb 15, 2011 at 19:31
  • 1
    Is that 4 chosen with an unbiased dice (thus making it really random). Commented Feb 15, 2011 at 19:49
  • looking at the error message, I wander perhaps your problem is elsewhere? Note the "passing const int as 'this'". Sounds weird perhaps the 4 argument is interpreted as this? why? Commented Feb 15, 2011 at 19:50
  • 1
    The question is not how many functions will have to be declared const, but whether those functions are actually const: do they modify any member of the object? If not, then mark them as const. Commented Feb 15, 2011 at 19:57

7 Answers 7

30
int Random() const { return var_ ? const_cast<ClassType*>(this)->newCall(4) : 0; } 

But it's not a good idea. Avoid if it's possible!

Sign up to request clarification or add additional context in comments.

3 Comments

Like you said, if you really need to use const_cast to accomplish this, try to refactor your design.
sometimes you can't help it.. the previous programmer over-designed, used all the fancy features in the language, and then left the company after his code gets too messy and unmaintainable..
Finally the reasonable answer instead of 'you must not do that'... There are always situations when you should or even encouraged to. For example, what to do if you want to provide const interface method and use the same logic for the non-const implementation? For example, imagine tree walking logic. Should you copypaste it for writing const accessors and non-const accessors for all nodes? Or just create clean const and non-const wrappers for those tasks?
20

you should alter your program to use/declare const correctly...

one alternative is to use const_cast.

7 Comments

Using const_cast incorrectly (which is what will happen hear) will lead to a complete disaster.
Thanks for the advice, I ended up changing the functions below newCall() and newCall() to all be const, because I didn't want to use const incorrectly.
@Grammin you're welcome. declaring it correctly has a lot of benefits. the most important (imo) is that it saves a ton of time in maintenance and readability. the compiler may quickly detect improper usage when the program changes. a side effect is that c++ starts to have so many consts written, that you think it would be nice if const were the default in some cases, and that a keyword was used to specify mutation instead :)
There is another way, using a proxy. stackoverflow.com/questions/8325400/…
@AlexandreVaillancourt If you just want example usage, here it is: learn.microsoft.com/en-us/cpp/cpp/const-cast-operator -- Avoid erasing const where possible and understand what qualifies as UB. Certainly, const_cast is superior to C style casting -- when you (truly) need it. The cases when you need it should be quite rare when dealing with well written, modern APIs. I primarily use it when dealing with C APIs. Fortunately, I don't have to use it often. Finally, the line I don't recommend would look like this: return var_ ? const_cast<TYPE*>(this)->newCall(4) : 0;.
|
5
const_cast<MyClass *>(this)->newCall(4) 

Only do this if you're certain newCall will not modify "this".

Comments

2

There are two possibilities here. First, newCall and ALL of its callees are in fact non-modifying functions. In that case you should absolutely go through and mark them all const. Both you and future code maintainers will thank you for making it much easier to read the code (speaking from personal experience here). Second, newCall DOES in fact mutate the state of your object (possibly via one of the functions it calls). In this case, you need to break API and make Random non-const to properly indicate to callers that it modifies the object state (if the modifications only affect physical constness and not logical constness you could use mutable attributes and propagate const).

Comments

0

Without using const casts, could you try creating a new instance of the class in the Random() method?

Comments

0

The const qualifier asserts that the instance this of the class will be unchanged after the operation, something which the compiler cant automagically deduce.

const_cast could be used but its evil

Comments

0

if it's really a random number generator, then the number generation code/state could likely be placed in a class-local static generator. this way, your object is not mutated and the method may remain const.

1 Comment

It's not a random number generator I just needed an example for SO. Thank you though

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.