#include<iostream>
using namespace std;
class X
{
int a;
int b;
public:
void f(int a)
{
cout<<"\nInside X";
}
virtual void abc ()
{
cout<<"\nHello X";
}
};
class Y : public X
{
int a;
public:
void f(int a, int b)
{
cout<<"\nInside Y";
}
void abc()
{
cout<<"\nHello Y";
}
};
int main()
{
X a;
cout<<sizeof(X);
Y b;
cout<<sizeof(Y);
X *h = new Y;
h->abc();
}
I understand that the reason the size of class X is 12 bytes, is because it contains a vptr (virtual pointer) to the virtual table. Is there anyway I could read this virtual table and if not, could at least access the virtual pointer. I tried using unions, but it gave me some kind of error.
Also, when I call h->abc() , how does it know the object of class, h is pointing to? I thought most of this was done at compile time. But when you have a base class pointer pointing to a derived class, how does it know which class function to execute.
Consider these two situations
X *h = new X;
h->abc();/* This would call the abc function in X */
and
X *h = new Y;
h->abc();/* This would call the abc function in Y*/
I read, that the h pointer would go to the vtable of the object it is pointing to and would hence call that function? But how is this achieved in runtime?
Ok you first question:I give you a example which may be better understanding!

#include<iostream>
using namespace std;
class Base1 {
public:
int ibase1;
Base1():ibase1(10) {}
virtual void f() { cout << "Base1::f()" << endl; }
virtual void g() { cout << "Base1::g()" << endl; }
virtual void h() { cout << "Base1::h()" << endl; }
};
class Base2 {
public:
int ibase2;
Base2():ibase2(20) {}
virtual void f() { cout << "Base2::f()" << endl; }
virtual void g() { cout << "Base2::g()" << endl; }
virtual void h() { cout << "Base2::h()" << endl; }
};
class Base3 {
public:
int ibase3;
Base3():ibase3(30) {}
virtual void f() { cout << "Base3::f()" << endl; }
virtual void g() { cout << "Base3::g()" << endl; }
virtual void h() { cout << "Base3::h()" << endl; }
};
class Derive : public Base1, public Base2, public Base3 {
public:
int iderive;
Derive():iderive(100) {}
virtual void f() { cout << "Derive::f()" << endl; }
virtual void g1() { cout << "Derive::g1()" << endl; }
};
This the memory rank of a derived class which implemented three base classes base1, base2, base3, where you :
Base1 *p1 = new Derive();
Base2 *p2 = new Derive();
Base3 *p3 = new Derive();
p1 will point the vtale1, p2 will point to vtable2, p3 will point to vtable3, If you call some virtual function it will find the very virtual table and get the address!
In your code:
X *h = new Y;
h will point to beginning position of the memory of Y, which is the virtual table of X,he will find the address of abc() which implemented in Y!
your second question:
The complier will consider the member function as the normal function, so it put the address of member function in the code section,so it does not occupied the memory!!
If you want to read the virtual table you can try like this:which is I tried in my example in gcc4.7
typedef void(*Func)(void);
Derive d;
int **pd = (int **)(&d);
int i = 0;
while(i < 4)
{
Func f = (Func)pd[0][i];
f();
i++;
}
int s = (int)(pd[1]);
cout << s << endl;
i = 0;
cout << "===============================================" << endl;
while(i < 3)
{
Func f = (Func)pd[2][i];
f();
i++;
}
s = (int)(pd[3]);
cout << s << endl;
cout << "===============================================" << endl;
i = 0;
while(i < 3)
{
Func f = (Func)pd[4][i];
f();
i++;
}
s = (int)(pd[5]);
cout << s << endl;
s = (int)(pd[6]);
cout << s << endl;
and you will get the result as follow:
Derive::f()
Base1::g()
Base1::h()
Derive::g1()
10
===============================================
Derive::f()
Base2::g()
Base2::h()
20
===============================================
Derive::f()
Base3::g()
Base3::h()
30
100
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With