1

Say I have a class Foo that has a member function which returns a non-const reference, that itself runs a member function that uses a const this pointer:

class Foo{
public:
    Foo& display(std::ostream& os) { do_display(os); return *this; }
private:
    void do_display(std::ostream& os) const { os << contents; }
    std::string contents;
}

When display runs do_display, the this pointer gets implicitly converted to a pointer to const. Why is it, then, that when do_display terminates, display is still able to change the object it was called on? As far as I know, it's not possible to assign a pointer to const to a pointer to non-const normally. Any insight is appreciated.

WhozCraig
  • 65,258
  • 11
  • 75
  • 141
JamesLens
  • 447
  • 6
  • 14
  • 3
    You can think of it like a parameter. if it has `const` added for one function, that doesn't affect the caller. – chris Feb 21 '14 at 15:24
  • only `do_display` can't change the object. `display` can. there's no magic here, as `this` is passed as first (hidden) parameter. – zoska Feb 21 '14 at 15:26
  • Non-const methods can change the object just fine, even if they call a const one. A method is just like another function with a hidden "first" parameter. – Medinoc Feb 21 '14 at 15:28
  • you pass a parameter by value (the pointer's one) so you can do whatever you want – Marco A. Feb 21 '14 at 15:29
  • Thanks, that makes sense. I wasn't sure if "this" was an implicit parameter or something that gets implicitly returned. – JamesLens Feb 21 '14 at 15:31

2 Answers2

2

Converting the non-const pointer in display in order to pass it to do_display creates a new pointer of a different type; it doesn't change the type of the existing pointer. Passing this to a member function is very similar to passing an argument to a non-member function:

// A non-const member function receives `this` as a non-const pointer
Foo& display(Foo * this, std::ostream & os) {
    // Pass a copy of `this`, converted to `Foo const *`
    do_display(this, os);

    // The local `this` is still `Foo *`
    return *this;
}

// A const member function receives `this` as a const pointer
void do_display(Foo const * this, std::ostream & os) {os << this->contents;}
Mike Seymour
  • 249,747
  • 28
  • 448
  • 644
  • Did you experience the copying with newer compilers? I currently work mostly with the old-fashioned ones. – Wolf Feb 21 '14 at 15:45
  • 1
    @Wolf: You don't "experience the copying", since the mechanism for passing `this` is hidden. The point is that passing it to another member function doesn't change its type in the calling function, in the same way that passing a normal argument wouldn't change the type of any local variables. – Mike Seymour Feb 21 '14 at 15:49
  • Ok, that's what I forgot: The `this` pointer is so omnipresent, that I didn't even remember that it has to be passed to member functions, and in cases like in the OP's example, the call will surely be optimized. – Wolf Feb 21 '14 at 15:54
  • Shouldn't the first argument to `do_display` be declared as `const Foo* this` rather than `Foo const* this`? I always thought the `this` pointer was a "pointer to constant object". – jia103 Feb 21 '14 at 15:55
  • @jia103 both forms mean the same. – Wolf Feb 21 '14 at 15:56
  • 1
    @jia103: Both are equivalent. I usually put the `const` after the thing it qualifies for consistency; but you can put it before the first thing if you want. – Mike Seymour Feb 21 '14 at 15:56
  • I think there is a `is` missing in the last sentence of the description. – Wolf Feb 21 '14 at 16:07
0

In C++ const access is often only a compile-time attribute [1] that is introduced to ease the control of the object's state. [2]

The method do_display() does not change anything of this but it restricts the access to read-only in its scope. After the call of the do_display() method returned, the access is read-write as before in the scope of the display() method.


[1] that's the reason for the option to cast const away, which can be considered safe if the constness is only a declarative one.

[2] see Item #3 in Effective C++: 55 Specific Ways to Improve Your Programs and Designs (3rd Edition): Scott Meyers or for example Const Correctness - C++ Tutorials - Cprogramming.com

Community
  • 1
  • 1
Wolf
  • 9,679
  • 7
  • 62
  • 108