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.