• Detail About How VPTR And Virtual Table Works


    this article is about how vptr and virtual table works,and it comes from http://www.dreamincode.net/forums/topic/45816-detail-about-how-vptr-and-virtual-table-works/

     

    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

    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

    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.

    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

    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:

    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:

    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:

    #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:

    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

    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

    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

    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 

     

    others about vptr and virtual :

    (1)http://blog.csdn.net/haoel/article/details/1948051

    (2)http://topic.csdn.net/u/20120413/22/4691a553-ab7d-4a5b-b14b-757a2676c328.html?64575

    (3)http://blog.csdn.net/hairetz/article/details/4137000

    (4)http://www.learncpp.com/cpp-tutorial/125-the-virtual-table/

     

     

     

     

     

     

     

     

     

     

  • 相关阅读:
    MySQL 字符集
    MySQL 存储引擎
    MySQL 常用函数
    MySQL 中的运算符
    MySQL 支持的数据类型
    SQL DCL 数据控制语句
    SQL DML 数据操纵语句
    SQL DDL 数据定义语句
    SQL 数据库结构化查询语言
    MySQL 服务常用操作命令
  • 原文地址:https://www.cnblogs.com/danshui/p/2449020.html
Copyright © 2020-2023  润新知