0
class A
{
void koo(){}
void foo() const {this->koo();}
};

int main()
{
A a;
a.foo();
}

I tried to call a non-const function inside const function.

error: passing ‘const A’ as ‘this’ argument of ‘void A::koo()’ discards qualifiers [-fpermissive]
  1. What is the meaning of this error?
  2. Can I use mutable keyword for this, If that, how? (as this post)
  3. Can I use const_cast for this. If that, how? (as this post)
  4. Are there ant other way to do this?
Community
  • 1
  • 1
Nayana Adassuriya
  • 23,596
  • 30
  • 104
  • 147
  • it means you are trying to call a non-const function from within a `const`. Nope. Yes - but hacky (`const_cast(this)->koo()`). Yes, make `koo()` `const` and any state it operates on `mutable`. – Nim Oct 08 '12 at 10:06
  • What are you actually trying to do inside of `koo()`? – juanchopanza Oct 08 '12 at 10:08
  • 1
    This is exactly the reason for the const qualifier, it prevents you executing non-const code on a const object. You may need to rethink your design, if you're having this problem, or maybe the function that your calling the non-const member function from really should be const. – goji Oct 08 '12 at 10:08
  • @Nim `const_cast` will lead to undefined behaviour if `koo` really mutates the object. – R. Martinho Fernandes Oct 08 '12 at 10:09
  • @R.MartinhoFernandes It won't, because it's called on a non-const object. And if called on a const object, it's undefined regardless of whether it mutates the object, is it not? –  Oct 08 '12 at 10:10
  • @hvd: I'm pretty sure it's OK to call a non-const function on a const object provided it doesn't mutate. But it's one of those cases where I claim there is no text in the standard saying X, which given the size of the standard is difficult to conclusively prove. – Steve Jessop Oct 08 '12 at 10:12
  • @SteveJessop I was under the impression that it was the same as calling a non-virtual method on a null pointer, or on an object of a different type, if it doesn't access any members: it won't fail in practise, but it's still invalid. I'll see if I can find a quote. –  Oct 08 '12 at 10:13
  • @hvd: there's nothing wrong in principle with creating a pointer-to-non-const that points to a const object. It's only writing through it that causes UB. The same is not true of `volatile`, btw: reading *or* writing through a pointer-to-non-volatile that points at a volatile object is UB. – Steve Jessop Oct 08 '12 at 10:14
  • If you change `koo();` to be `koo() const;`, make sure it isn't an override for a virtual function, as you'll be declaring a new function overload rather than overriding the virtual base. – Peter Wood Oct 08 '12 at 10:16
  • @R.MartinhoFernandes, wasn't sure of the UB, but sure is hacky, which in my book is a Bad Thing(tm)... – Nim Oct 08 '12 at 10:23
  • @SteveJessop I think you're right. There's a special exception that makes it invalid to call nonstatic member functions for invalid values of `this` that would be valid if `this` were an explicit pointer argument of a static/non-member function ([class.mfct.non-static]p2). That exception doesn't say anything about `const`/`volatile`, and the text that follows that describes the `const`/`volatile` modifies doesn't say any such thing either. –  Oct 08 '12 at 10:24
  • @hvd "And if called on a const object, it's undefined regardless of whether it mutates the object, is it not?" is exactly the crux of the matter: if you're going to make it impossible to call on a const object, C++ has a way to do that: remove the const qualifier (don't make UB easy!). Client code can then `const_cast` itself if it knows the object is not really const. If you want to make it possible to work on a const object, C++ also has a way to do that: make the fields `mutable`. Basically, I think using `const_cast` to cause mutation on a `const` function is the wrongest of all options. – R. Martinho Fernandes Oct 08 '12 at 10:33

4 Answers4

4
  1. In function foo, this has type const A*. In order to call a non-const function on it, you'd end up with this in koo having the same value but type A*, i.e. it would discard const qualifiers.

  2. No.

  3. You could, because you happen to know that the koo function doesn't modify any const objects that are data members of A (because (a) the function body is empty and (b) A has no data members and (c) it's called on a non-const instance of A anyway). But don't do that.

  4. Mark koo as a const member function, same as foo.

Steve Jessop
  • 273,490
  • 39
  • 460
  • 699
1

koo isn't declared as const, this indicates that it could change the object somehow, which isn't allowed on const objects. The signature of foo indicates that the current object (this) should be considered to be constant.

You'll need to specify a const variant of koo:

void koo() const {}
void koo() {}
Zeta
  • 103,620
  • 13
  • 194
  • 236
  • And if the original `koo` doesn't change the object's state, it's not even necessary to overload: just add `const` to the original method. –  Oct 08 '12 at 10:09
  • 1
    @hvd Unless koo is a virtual function in which case changing to const will mean the base version isn't overridden any-more. – Peter Wood Oct 08 '12 at 10:13
  • @PeterWood Good point. In that case, add `const` to the original method, and make the non-const override call the const version. Technically that's an overload, but you don't end up with two separate implementations. –  Oct 08 '12 at 10:16
0

if koo is declared not const (ie it modifies the internal state of the object) then indeed foo is not const.

Either make kooconst, foo not const, or if the object act like "with no state" but has internal variables that must be updated, then make these variables mutable.

mutable int m_accessCount;
log0
  • 10,489
  • 4
  • 28
  • 62
0

When you declare a function as const, you are saying "this function does never change the object". This allows you to use the function on const objects.

In your case, you are calling a non-const function from inside of a const one, which means that you cannot ensure the object will not change. This leads to an error, since the const on foo() implies the object must not change in any case.

Please avoid using const_cast, since it can cause UB if used improperly.

The best way to fix it is to provide a const version of koo(). Either write a non-modifying version of it, or (if it doesn't modify the object as it is) just add the const keyword.

SingerOfTheFall
  • 29,228
  • 8
  • 68
  • 105