Relation between "this" and "VPTR"

Hi Techgurus,

I understand the meaning and functionalities of both of the in built pointers.
THIS : it is a pointer automatically invoked in the member functions , which holds the address of the current object so that member functions will know for which object they have been called for.

VPTR : When we mention a function as virtual to let the compiler know that it is late binding then every clas with a virtual function or derived from it will have a vtable and a vptr which will point to the starting address of the vtable.

My confusion is how "THIS" and "VPTR" are related and how they come into the picture in hierarchy wise.

Kindly help.
in short terms this pointer allways points to a member of this class while
virtual pointer points to a member either of derived class, this class or base class.
they are related so that vptr can point to many "this" pointers trought the vtable.
Last edited on
In that case if we have this pointer , then why do we need a vptr separately ?
picture tell's tousand of words:
http://www.cs.ust.hk/~dekai/library/ECKEL_Bruce/TICPP-2nd-ed-Vol-one/TICPP-2nd-ed-Vol-one-html/TIC2Vo16.gif

edit:
in the picture above, you can see that VPTR (on the left) points to many this pointers (on the right, "vtable")

In that case if we have this pointer , then why do we need a vptr separately ?

because the vptr is the one who invkes the right this pointer.
without vptr inheritance will be with no polymorphizm
Last edited on
The this pointer is not necessary stored anywhere in memory. It's just a language keyword that allows you to get a pointer to the object that the function was invoked on.
@codekiddy

Thanks for the reply.

@Peter87
can you please explain little more
The vptr is a pointer that is stored in each object so it will increase the size of each object. A vptr is only needed if the class has virtual functions so if the class has no virtual functions the objects will not contain vptrs.

The this pointer is never stored in each object, so it doesn't contribute to the size of the object.
@all thanks for the replies , but I am still confused kindly bear with me the book thinking in c++ says :
"remember that the starting address corresponds to the value of this , and this is quietly pushed on to the stack as an argument before any function call, so the member function knows which particular object it is working on"

That is why I am getting confused that if we have this function which determines already which object it is working on , why do we need an extra pointer "VPTR"?

And then the next confusion as codekiddy has said VPTR invokes this pointer , but the book says
"First, the VPTR must be produces , so the VTABLE can be found. For this compiler the VPTR is inserted at the beginning of the object , so the contents of this corresponds to the VPTR . The line
mov bx, word ptr[si] // it's an example provided in the book. fetches the word that si(that is, this), points to , which is the VPTR."

Which means the this pointer points to VPTR and not the VPTR invokes this pointer, can someone please help me to understand it. I am totally lost here.
Last edited on
as codekiddy has said VPTR invokes this pointer
in fact this is not a pointer at all, maybe it "looks" as a pointer because you can write this-> so one would think that it's a pointer but it's not..
this is only an address of the object so that methond is invoked on right object. how the addres is stored or not is implementation dependent.

if you look again at the picture above I posted you will notice that there is a & before every method in vtable, and this is actually the this "pointer" or address which is invoked by virtual pointer.

and this is quietly pushed on to the stack as an argument before any function call, so the member function knows which particular object it is working on
this is not a rule, it could also be stored in the registers.

hat is why I am getting confused that if we have this function which determines already which object it is working on , why do we need an extra pointer "VPTR"?

because one class can be inherited and their methods can be overriden, and how do know against which object to invoke the method if there is no vptr then?

please note that there is only one member method which is invoked by many objects of the same class, member methods are not the same thing as data members which are not shared of course.

Which means the this pointer points to VPTR and not the VPTR invokes this pointer
yes, as I said this is just an address, and without an address things can't be pulled out of memory.
so in order to get the vptr you need it's address, and the address it this

this all leads verry low, and I see no reason why would you learn such low things ?
Last edited on
Thanks codekiddy

because one class can be inherited and their methods can be overriden, and how do know against which object to invoke the method if there is no vptr then?

Isn't what this will do? sorry I am new to this so probably asking all sorts of stupid questions . But I still have doubt kindly bear with me.
Last edited on
sorry for being not precize, my above statement you quoted applies to polymorphizm.

what does that mean?
consider this example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include <iostream>
using namespace std;

class Base
{
public:
	virtual ~Base() = default;
	virtual void f() { std::cout << "base"; }
};

class Derived : public Base
{
	void f() override { std::cout << "derived"; }
};

int main()
{
	Base* ptr = new Derived;

	ptr->f(); // calls Derived::f() not Base::f()

	delete ptr;

	cin.ignore();

	return 0;
}


program output:
derived

yes derived not base!

here you have a pointer to the base class but invoking the pointer does not call the function of base class but instead of derived class!

how is this possible??
because there is a vpt in Base cass which invokes the function from derived class instead.

how does vptr know the address?
trough this pointer of derived class.

how is vptr invoked?
trough this pointer of base class.

where this is an address which should be known.

if there would be no vptr then this whole thing would not work and the base methond would be invoked instead of derived method.
you can test this by "removing" vptr from the code, ie making function non virtual.
Last edited on
Think of this as a parameter that gets passed to every non-static member function. The compiler inserts it in every declaration and in every call. When you access a data member x of the class, the compiler basically converts it to this->x. In other words, if you have this:
1
2
3
4
5
6
7
8
9
10
11
12
13
class A {
  void f();
  int i;
};

void A::f()
{
   i = 10;
}

...
A myA;
myA.f();


The compiler basically converts it to:
1
2
3
4
5
6
7
8
9
10
11
12
13
class A {
  void f(A const *this);
  int i;
};

void A::f(A const *this)
{
   this->i = 10;
}

...
A myA;
A::f(&myA);



Again, the key here is that this is a parameter to member functions. It exists only inside a member function.

The vptr, (which is a compiler implementation detail), is like a hidden member of the class. It points to the virtual table. Consider.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class base {
public:
    virtual void f() {cout << "I am base\n"; }
    void g() { f(); }
};

class derived : public base {
public:
    virtual void f() {cout << "I am derived\n"; }
};
...
derived d;
base *b = &d;
b->g();


Base::g(), has a pointer to an instance of base. But when it calls f(), how does it know which function to call? Indeed, it may need to call a function that wasn't even written yet when class base was compiled! The way it does this is through the vtbl pointer.

So in summary:
- this is a parameter to every non-static member function that the compiler inserts for you.
- vtbl is a "hidden member" of every class that contains virtual functions.

This points out a couple of disadvantages of virtual functions:
- They make instances of the class larger in memory because each instance must hold the vtbl pointer.
- Because the vtable points to every virtual function, your program will contain every virtual function of the class, even ones that it never calls.

Hope this helps.
@dhyaden thanks for the reply

I understand the difference between this and vptr but whwere I am getting confused is thinking in c++ says this will fetch vptr , so my doubt is if this is there in the picture even for the dynamic binding , why do we need vptr at all because this gives us the address of the current object for which the member function has been called.
@ all
1
2
Base* ptr = new Derived;
ptr->f(); 


For the above code as the base class has a virtual keyword, it won't do early binding and will take the vptr of the base class which will point to the virtual table of the base class so, ultimately won't it give us the f() of the base class ? like ptr->vptr(of base class)->f()(of base class only), then how are we getting f() of derived class?
Last edited on
What I have understood from thinking in c++ , when we do upcasting without declaring virtual function in the base class the objects do not have any type information and also compiler takes(with the help of this) the objects of the derived class as the base class's object only and so base class' s member function is called a
.. and then when we mention virtual function this fetches the vptr for the object which points to the vtable which gives the type information so the right function gets called.
yepMe, I think I see the source of your confusion. When you class Base and class Derived, each instance has a vptr, but they point to DIFFERENT vtables. In the vtable for class Base is a pointer to Base::f. In the vtable for class Derived is a pointer to Derived::f.

When you construct a Base object, that instance's vptr points to Base's vtable. But when you construct a Derived object, the vptr points to Derived's vtable.

In other words
- there is ONE vtable for class Base and ONE vtable for class Derived.
- Each instance of Base or Derived contains a hidden vptr member
- The vptr member points to the Base vtable OR the Derived vtable.
- When you call virtual function f the compiler inserts code to look up the vtable through the vptr, then get the pointer to the f function, then call it.
- Depending on on WHICH TABLE to the vptr points to, this process will call Base::f() or Derived::f.
Topic archived. No new replies allowed.