Page 1 of 1

... introducing the amazing this pointer Describes a magical feature of the this pointer Rate Topic: -----

#1 Martyn.Rae  Icon User is offline

  • The programming dinosaur
  • member icon

Reputation: 540
  • View blog
  • Posts: 1,406
  • Joined: 22-August 09

Posted 04 March 2010 - 07:51 AM

*
POPULAR

... introducing the amazing this pointer

Question Time

Here is a little quiz for you.

1. Do you think that the this pointer is a constant that can't be changed
in a member function without resorting to some underhand mechanism?
2. Do you think that the this pointer is like any other pointer?
3. Do you think that the this pointer points to the first member variable
in your class?
4. Do you think that it is possible in C++ to assign a new value to a pointer without
ultimately having to use an assignment operator?

If your answer is yes to questions 1, 2 and 3 and no to question 4 then be prepared to be amazed!!!

Introduction

Most of us see the this pointer as a pointer to a class. Let's take an example.

class foo {
    public:
        int foobar;
    public:
        foo(int bar) : foobar(bar) { }
        void print() {
            cout.flags(cout.flags() | ios_base::hex);
            cout << "the \'this\' address is 0x" << this << ", \'foobar\' address is 0x" << &foobar;
        }
};

int main () {
    foo foobar(10);

    foobar.print();
}



Now, if we run this little program you will get printed something like this

the 'this' address is 0x003FF784, 'foobar' address is 0x003FF784

printed out. So, you may think I was correct when I answered yes to question 3. The this pointer does point to the first member variable in my class. OK, I concede a point you were correct for the moment. Let's just add another line to our class.

class foo {
    public:
        int foobar;
    public:
        foo(int bar) : foobar(bar) { }
        void print() {
            cout.flags(cout.flags() | ios_base::hex);
            cout << "the \'this\' address is 0x" << this << ", \'foobar\' address is 0x" << &foobar;
        }
        virtual void not_used() { };
};

int main () {
    foo foobar(10);

    foobar.print();
}



Now run the program again and you will get something like this

the 'this' address is 0x001AFA48, 'foobar' address is 0x001AFA4C

printed out. Yipes, you will shout, how is that possible? The this pointer is now not pointing to my first member variable ... what has happened?

Virtual functions and the vtable

What has happened is the class has been given a vtable pointer. The vtable pointer points to a table of all virtual function member addresses for the class. Our class has just one virtual function, so there would be one pointer to the not_used() function in the vtable. This is the way that virtual functions are handled by the compiler. So the answer to questions 2 and 3 is no. The this pointer is not like any other pointer and no, the this pointer does not necessarily point to the address of the first member variable in your class.

The morphing this pointer

It is possible to change the this pointer in a member function. Let's look at some code.

#include <iostream> 
 
using namespace std; 

class state {
    private:
        int this_state;
    public:
        state(int new_state) : this_state(new_state) { };
        virtual state * change_state() = 0;
};

class state_1 : public state {
    public:
        state_1() : state(1) { };
        state * change_state();
};

class state_2 : public state {
    public:
        state_2() : state(2) { };
        state * change_state();
};

state *  state_1::change_state() {
    cout << "state_1" << endl; 
    reinterpret_cast<state_2 *>(this)->state_2::state_2(); 
    return this; 
};

state *  state_2::change_state() {
    cout << "state_2" << endl; 
    reinterpret_cast<state_1 *>(this)->state_1::state_1(); 
    return this; 
};


int main () {
    state * current_state = new state_1();
    current_state = current_state->change_state();
    current_state = current_state->change_state();
    current_state = current_state->change_state();
    current_state = current_state->change_state();
}



We have a base class called state, and two derived classes called state_1 and state2. Noice that the base class state has a pure virtual method called change_state. That is to ensure that the base class cannot be instanciated, and forces the derived classes to declare that function. The constructor of the base class and the derived classes is not really of importance here. What is important is the change_state code. Now let's look at the state_1::change_state() method carefully.

state *  state_1::change_state() {
    cout << "state_1" << endl; 
    reinterpret_cast<state_2 *>(this)->state_2::state_2(); 
    return this; 
};



On entering this method, we print out "state_1" to the console. The next line says reinterpret the this pointer as if it was a state_2 pointer and call the state_2 constructor. Then return the this pointer to the caller. Now that might seem a little pointless to you, but trust me it's not. What has happened is the this pointer has magically morphed itself into a pointer to a state_2 object, and is no longer a state_1 object. Don't believe me? Compile and run the code. You will be amazed to find that the output is as follows:-

state_1
state_2
state_1
state_2



We have changed the this pointer from one type of derived class into another type of derived class without making any kind of assignment to it. Magic don't you agree!!!

Epilogue

The significance of this little piece of magic does not have any great significance for general software design. I only discovered this by chance when I was looking at using C++ to build a particular parser for a customer quite a few years ago. I do not know if the code works on the linux implementation of C++, or for that matter any other C++ compiler. It does work for Microsoft Visual Studio C++, and that is where I live. Please try it on other compilers and comment me back either on this tutorial or via PM.

Is This A Good Question/Topic? 6
  • +

Replies To: ... introducing the amazing this pointer

#2 sarmanu  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 966
  • View blog
  • Posts: 2,362
  • Joined: 04-December 09

Posted 05 March 2010 - 06:56 AM

Nice tricks you found about "this" pointer. Good tutorial!
Was This Post Helpful? 0
  • +
  • -

#3 vividexstance  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 662
  • View blog
  • Posts: 2,273
  • Joined: 31-December 10

Posted 03 February 2011 - 09:25 PM

When I try to compile the exact code you posted with g++ version=4.4.3 on Ubuntu 10.04 LTS
command-line is:
g++ state.cpp -o state

the error is:
state.cpp: In member function ‘virtual state* state_1::change_state()’:
state.cpp:28: error: invalid use of ‘class state_2’
state.cpp: In member function ‘virtual state* state_2::change_state()’:
state.cpp:34: error: invalid use of ‘class state_1’

Was This Post Helpful? 0
  • +
  • -

Page 1 of 1