0

Why is it that get_controlState2 is fine being const but get_controlState gives error passing 'const Main' as 'this' argument discards qualifiers?

#include <iostream>

class Main {
public:
    int getData() { return 123; } // Actually returns a mutable object

    int get_controlState() const {
        return this->getData(); // Error
    }
};

class Controller {
public:
    Controller(Main* pMain) : pMain{pMain} { }
    
    int get_controlState2() const {
        return pMain->getData(); // Fine
    }
    
private:
    Main* pMain;
};

int main() {
    Main main;
    Controller controller{&main};

    std::cout << main.get_controlState() << std::endl;
    std::cout << controller.get_controlState2() << std::endl;

    return 0;
}

https://www.mycompiler.io/view/5xousuHcDdN

This is very similar to calling non-const function on non-const member in const function, but not exact. He has a library function that could be const but isn't because they cannot change it. In my case it returns a mutable object which is only read out, but works in some circumstances

His question is answered with "in a const function all members are const too", but this seems to contradict get_controlState2.

What I'm trying to do is remove the delegate from Controller and put the function in Main instead.

Mark Jeronimus
  • 9,278
  • 3
  • 37
  • 50
  • 4
    In `Controller::get_controlState2() const`, your pointer `pMain` is `const`, but `*pMain` is **not** `const`. A _const pointer to something_ is not the same as a _pointer to something that's const_. – Drew Dormann Mar 17 '23 at 16:11
  • Inside a `const` member function the type of `this` is `const *`. – rustyx Mar 17 '23 at 16:14
  • 1
    @DrewDormann that should be posted as an answer instead of a comment – Remy Lebeau Mar 17 '23 at 18:33

1 Answers1

0

Your function int Main::get_data() is not const, and therefore can not be called from a const Main.

You seem to understand that.

Your definition of Main::get_controlState() is const, so it operates on a const Main, so you get an error:

int get_controlState() const {
    return this->getData(); // Error
}

Your definition of Controller::get_controlState() operates on a Main that is not const. so it compiles.

int get_controlState2() const {
    return pMain->getData(); // Fine
}

The member function is const, which makes member variable pMain const. It's a const pointer. But that does not make the object it points to const.

A const pointer to something is not the same as a pointer to something that's const.

Drew Dormann
  • 59,987
  • 13
  • 123
  • 180
  • You're right. I can even add a statement that *mutates* `pMain` inside the const function. This is totally crazy, and may I add, DANGEROUS. Why is a const method allowed to change state? Shouldn't const be a *protective* construct to prevent programmers from accidentally modifying state? This goes straight against the 'clean code' practice. – Mark Jeronimus Mar 20 '23 at 08:22
  • That's not correct - you can not mutate `pMain` in a `const` member function. Try `pMain = nullptr;` in your const member function. It will not compile, because you are trying to modify `pMain`. You can, however, modify variables that are not members of the class, such as `Main main;`. – Drew Dormann Mar 20 '23 at 13:27
  • I phrased that wrong. When I say I mutate `pMain`, I meant the object. Otherwise I'd say 'changes pMain' – Mark Jeronimus Mar 21 '23 at 18:11