Welcome to Dream.In.Code
Getting C++ Help is Easy!

Join 109,719 C++ Programmers for FREE! Ask your question and get quick answers from experts. There are 2,028 online right now! We've got more than 500 tutorials and 2,000 snippets. Join and find out why Dream.In.Code is the #1 programming help community on the internet! Registration is fast and FREE... Join Now!



Detail about How VPTR and Virtual table works

 
Reply to this topicStart new topic

> Detail about How VPTR and Virtual table works, Virtual function un C++

Rating  5
asadullah.ansari
Group Icon



post 11 Mar, 2008 - 12:48 AM
Post #1


Assumption: machine is 32-bit .
Here I am going to explain How Virtual table, Virtual pointer for Virtual functions are internally working.

First we have understand memory layout.

Example 1: How the class's memory layout
CODE

class Test
{
  public:
    int data1;
    int data2;
    int fun1();
};

int main()
{
  Test obj;
  cout << "obj's Size = " << sizeof(obj) << endl;
  cout << "obj 's Address = " << &obj << endl;
  return 0;
}

Output:

Sobj's Size = 8
obj 's Address = 0012FF7C

Note: Any Plane member function does not take any memory.


Example 2: Memory Layout of Derived class
CODE

class Test
{
public:
  int a;
  int b;
};

class dTest : public Test
{
public:
  int c;
};

int main()
{
  Test obj1;
  cout << "obj1's Size = " << sizeof(obj1) << endl;
  cout << "obj1's Address = " << &obj1 << endl;
  dTest obj2;
  cout << "obj2's Size = "<< sizeof(obj2) << endl;
  cout << "obj2's Address = "<< &obj2 << endl;
  return 0;
}

OUTPUT:
obj1's Size = 8
obj1's Address = 0012FF78
obj2's Size = 12
obj2's Address = 0012FF6C

Example 3: Memory layout If we have one virtual function.
CODE

class Test
{
public:
  int data;
  virtual void fun1()
  {
    cout << "Test::fun1" << endl;
  }
};

int main()
{
  Test obj;
  cout << "obj's Size = " << sizeof(obj) << endl;
  cout << "obj's Address = " << &obj << endl;
  return 0;
}

OUTPUT:

obj's Size = 8
obj's Address = 0012FF7C

Note: Adding one virtual function in a class takes 4 Byte extra.

Example 4: More than one Virtual function
CODE

class Test
{
public:
  int data;
  virtual void fun1() { cout << "Test::fun1" << endl; }
  virtual void fun2() { cout << "Test::fun2" << endl; }
  virtual void fun3() { cout << "Test::fun3" << endl; }
  virtual void fun4() { cout << "Test::fun4" << endl; }
};

int main()
{
  Test obj;
  cout << "obj's Size = " << sizeof(obj) << endl;
  cout << "obj's Address = " << &obj << endl;
  return 0;
}

OUTPUT:

obj's Size = 8
obj's Address = 0012FF7C

Note: Adding more virtual functions in a class, no extra size taking i.e. Only one machine size taking(i.e. 4 byte)

Example 5:
CODE

class Test
{
public:
  int a;
  int b;
  Test(int temp1 = 0, int temp2 = 0)
  {
     a=temp1;
     b=temp2;
  }
  int getA()  
  {
     return a;
  }
  int getB()  
  {
     return b;
  }
  virtual ~Test();
};

int main()
{
  Test obj(5, 10);

// Changing a and b
  int* pInt = (int*)&obj;
  *(pInt+0) = 100;  
  *(pInt+1) = 200;  

  cout << "a = " << obj.getA() << endl;
  cout << "b = " << obj.getB() << endl;
  return 0;
}

OUTPUT:
a = 200
b = 10

If we Change the code as then

// Changing a and b
int* pInt = (int*)&obj;
*(pInt+1) = 100; // In place of 0
*(pInt+2) = 200; // In place of 1

OUTPUT:
a = 100
b = 200

Note: Who sits 1st place of Class : Answer is VPTR
VPTR - 1st placed in class and rest sits after it.



Example 6:
CODE

class Test
{
  virtual void fun1()
  {
     cout << "Test::fun1" << endl;
  }
};

int main()
{
  Test obj;
  cout << "VPTR's Address " << (int*)(&obj+0) << endl;
  cout << "VPTR's Value " << (int*)*(int*)(&obj+0) << endl;
  return 0;
}

OUTPUT:

VPTR's Address 0012FF7C
VPTR's Value 0046C060

NOTE: This VPTR's value is a address of Virtual table. Lets see in next Example.

Example 7:
CODE

#include <iostream>
using namespace std;

class Test
{
   virtual void fun1()
   {
    cout << "Test::fun1" << endl;
   }
};
typedef void (*Fun)(void);

int main()
{
  Test obj;
  cout << "VPTR's Address " << (int*)(&obj+0) << endl;
  cout << " VIRTUAL TABLE 's Address " << (int*)*(int*)(&obj+0) << endl; // Value of VPTR
  cout << "Value at first entry of VIRTUAL TABLE " << (int*)*(int*)*(int*)(&obj+0) << endl;
  
  Fun pFun = (Fun)*(int*)*(int*)(&obj+0);   // calling Virtual function
  pFun();
  return 0;
}

OUTPUT:
VPTR's Address 0012FF7C
VIRTUAL TABLE 's Address 0046C0EC
Value at first entry of VIRTUAL TABLE 0040100A
Test: fun1


Example 8:

CODE

class Test
{
  virtual void fun1() { cout << "Test::fun1" << endl; }
  virtual void func1() { cout << "Test::func1" << endl; }
};

int main()
{
  Test obj;

  cout << "VPTR's Address " << (int*)(&obj+0) << endl;
  cout << "VIRTUAL TABLE 's Address"<< (int*)*(int*)(&obj+0) << endl;

  // Calling Virtual table functions
  cout << "Value at 1st entry of VTable " << (int*)*((int*)*(int*)(&obj+0)+0) << endl;
  cout << "Value at 2nd entry of VTable " << (int*)*((int*)*(int*)(&obj+0)+1) << endl;

  return 0;
}

OUTPUT:

VPTR's Address 0012FF7C
VIRTUAL TABLE 's Address 0046C0EC
Value at first entry of VIRTUAL TABLE 0040100A
Value at 2nd entry of VIRTUAL TABLE 004012


Example :9
CODE

class Test
{
  virtual void fun1() { cout << "Test::fun1" << endl; }
  virtual void func1() { cout << "Test::func1" << endl; }
};

typedef void(*Fun)(void);

int main()
{
  Test obj;
  Fun pFun = NULL;
  
  // calling 1st virtual function
  pFun = (Fun)*((int*)*(int*)(&obj+0)+0);
  pFun();

  // calling 2nd virtual function
  pFun = (Fun)*((int*)*(int*)(&obj+0)+1);
  pFun();

  return 0;
}

OUTPUT:

Test::fun1
Test::func1

Example 10: multiple Inheritance
CODE

class Base1
{
public:
  virtual void fun();
};

class Base2
{
public:
  virtual void fun();
};

class Base3
{
public:
  virtual void fun();
};

class Derive : public Base1, public Base2, public Base3
{
};

int main()
{
  Derive obj;
  cout << "Derive's Size = " << sizeof(obj) << endl;
  return 0;
}

OUTPUT:

Derive's Size = 12


Example 11: Calling Virtual Functions in case of Multiple Inheritance
CODE

class Base1
{
  virtual void fun1() { cout << "Base1::fun1()" << endl; }
  virtual void func1() { cout << "Base1::func1()" << endl; }
};

class Base2 {
  virtual void fun1() { cout << "Base2::fun1()" << endl; }
  virtual void func1() { cout << "Base2::func1()" << endl; }
};

class Base3 {
  virtual void fun1() { cout << "Base3::fun1()" << endl; }
  virtual void func1() { cout << "Base3::func1()" << endl; }
};

class Derive : public Base1, public Base2, public Base3
{
public:
  virtual void Fn()
  {
  cout << "Derive::Fn" << endl;
  }
  virtual void Fnc()
  {
  cout << "Derive::Fnc" << endl;
  }
};

typedef void(*Fun)(void);

int main()
{
  Derive obj;
  Fun pFun = NULL;
  
  // calling 1st virtual function of Base1
  pFun = (Fun)*((int*)*(int*)((int*)&obj+0)+0);
  pFun();

  // calling 2nd virtual function of Base1
  pFun = (Fun)*((int*)*(int*)((int*)&obj+0)+1);
  pFun();

  // calling 1st virtual function of Base2
  pFun = (Fun)*((int*)*(int*)((int*)&obj+1)+0);
  pFun();

  // calling 2nd virtual function of Base2
  pFun = (Fun)*((int*)*(int*)((int*)&obj+1)+1);
  pFun();

  // calling 1st virtual function of Base3
  pFun = (Fun)*((int*)*(int*)((int*)&obj+2)+0);
  pFun();

  // calling 2nd virtual function of Base3
  pFun = (Fun)*((int*)*(int*)((int*)&obj+2)+1);
  pFun();

  // calling 1st virtual function of Drive
  pFun = (Fun)*((int*)*(int*)((int*)&obj+0)+2);
  pFun();

  // calling 2nd virtual function of Drive
  pFun = (Fun)*((int*)*(int*)((int*)&obj+0)+3);
  pFun();

  return 0;
}

OUTPUT:

Base1::fun
Base1::func
Base2::fun
Base2::func
Base3::fun
Base3::func
Drive::Fn
Drive::Fnc


By
Asadullah Ansari
Go to the top of the page
+Quote Post


Register to Make This Ad Go Away!

nitin_c_c++
Group Icon



post 24 Jun, 2008 - 10:51 PM
Post #2
Explanation is very good and helpful.
Go to the top of the page
+Quote Post


Reply to this topicStart new topic
2 User(s) are reading this topic (2 Guests and 0 Anonymous Users)
0 Members:

 

Lo-Fi Version Time is now: 9/8/08 09:21AM

Live C++ Help!

C++ Tutorials

Reference Sheets

C++ Snippets

Bye Bye Ads

Free DIC T-Shirt

T-Shirt Example

Related Sites

Monthly Drawing

Thumb Drive

Partners

Top Contributors

Top 10 Kudos This Month