How to call a non-const function within a const function (C++)

35,552

Solution 1

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

one alternative is to use const_cast.

Solution 2

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

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

Solution 3

const_cast<MyClass *>(this)->newCall(4)

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

Solution 4

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).

Share:
35,552

Related videos on Youtube

Grammin
Author by

Grammin

Updated on July 09, 2022

Comments

  • Grammin
    Grammin almost 2 years

    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

    • GWW
      GWW over 13 years
      You could make Random() non-const.
    • Grammin
      Grammin over 13 years
      I would like to but Random() is legacy code that I can't really touch.
    • Martin York
      Martin York over 13 years
      Is that 4 chosen with an unbiased dice (thus making it really random).
    • davka
      davka over 13 years
      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?
    • David Rodríguez - dribeas
      David Rodríguez - dribeas over 13 years
      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.
  • Grammin
    Grammin over 13 years
    It's not a random number generator I just needed an example for SO. Thank you though
  • Martin York
    Martin York over 13 years
    Using const_cast incorrectly (which is what will happen hear) will lead to a complete disaster.
  • Grammin
    Grammin over 13 years
    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.
  • justin
    justin over 13 years
    @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 :)
  • Janosimas
    Janosimas about 9 years
    There is another way, using a proxy. stackoverflow.com/questions/8325400/…
  • thatWiseGuy
    thatWiseGuy over 8 years
    Like you said, if you really need to use const_cast to accomplish this, try to refactor your design.
  • Vaillancourt
    Vaillancourt almost 7 years
    "one alternative is to use const_cast."... How should they use const_cast?
  • justin
    justin almost 7 years
    @AlexandreVaillancourt The point I make in my answer is that "you should alter your program to use/declare const correctly...". Using const_cast in the OP's scenario is an alternative which can be used to remove const from this. The implication I made 6 years ago (and today) is that you should not use const_cast to accomplish this because a) It will be confusing and incorrect and b) It can result in Undefined Behavior. Good examples of when to use const_cast is to introduce const or modify const, volatile, __unaliged qualifiers (in cases you know it is safe and legal).
  • justin
    justin almost 7 years
    @AlexandreVaillancourt If you just want example usage, here it is: docs.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;.
  • Zennichimaro
    Zennichimaro over 5 years
    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..
  • avtomaton
    avtomaton over 3 years
    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?