zoukankan      html  css  js  c++  java
  • Virtual method table

    https://en.wikipedia.org/wiki/Virtual_method_table

    The g++ compiler implements the multiple inheritance of the classes B1 and B2 in class D using two virtual method tables, one for each base class. (There are other ways to implement multiple inheritance, but this is the most common.) This leads to the necessity for "pointer fixups", also called thunks, whencasting.

    Example
    
    Consider the following class declarations in C++ syntax:
    
    class B1 {
    public:
      void f0() {}
      virtual void f1() {}
      int int_in_b1;
    };
    
    class B2 {
    public:
      virtual void f2() {}
      int int_in_b2;
    };
    
    used to derive the following class:
    
    class D : public B1, public B2 {
    public:
      void d() {}
      void f2() {}  // override B2::f2()
      int int_in_d;
    };
    
    and the following piece of C++ code:
    
    B2 *b2 = new B2();
    D  *d  = new D();
    
    g++ 3.4.6 from GCC produces the following 32-bit memory layout for the object b2:[nb 1]
    
    b2:
      +0: pointer to virtual method table of B2
      +4: value of int_in_b2
    
    virtual method table of B2:
      +0: B2::f2()   
    
    and the following memory layout for the object d:
    
    d:
      +0: pointer to virtual method table of D (for B1)
      +4: value of int_in_b1
      +8: pointer to virtual method table of D (for B2)
     +12: value of int_in_b2
     +16: value of int_in_d
    
    Total size: 20 Bytes.
    
    virtual method table of D (for B1):
      +0: B1::f1()  // B1::f1() is not overridden
    
    virtual method table of D (for B2):
      +0: D::f2()   // B2::f2() is overridden by D::f2()
    
    Note that those functions not carrying the keyword virtual in their declaration (such as f0() and d()) do not generally appear in the vtable. There are exceptions for special cases as posed by the default constructor.
    
    Overriding of the method f2() in class D is implemented by duplicating the virtual method table of B2 and replacing the pointer to B2::f2() with a pointer to D::f2().
    Multiple inheritance and thunks
    
    The g++ compiler implements the multiple inheritance of the classes B1 and B2 in class D using two virtual method tables, one for each base class. (There are other ways to implement multiple inheritance, but this is the most common.) This leads to the necessity for "pointer fixups", also called thunks, when casting.
    
    Consider the following C++ code:
    
    D  *d  = new D();
    B1 *b1 = static_cast<B1*>(d);
    B2 *b2 = static_cast<B2*>(d);
    
    While d and b1 will point to the same memory location after execution of this code, b2 will point to the location d+8 (eight bytes beyond the memory location of d). Thus, b2 points to the region within d which "looks like" an instance of B2, i.e., has the same memory layout as an instance of B2.
    Invocation
    
    A call to d->f1() is handled by dereferencing d's D::B1 vpointer, looking up the f1 entry in the vtable, and then dereferencing that pointer to call the code.
    
    In the case of single inheritance (or in a language with only single inheritance), if the vpointer is always the first element in d (as it is with many compilers), this reduces to the following pseudo-C++:
    
    (*((*d)[0]))(d)
    
    Where *d refers to the virtual method table of D and [0] refers to the first method in the vtable. The parameter d becomes the "this" pointer to the object.
    
    In the more general case, calling B1::f1() or D::f2() is more complicated:
    
    (*(*(d[+0]/*pointer to virtual method table of D (for B1)*/)[0]))(d)   /* Call d->f1() */
    (*(*(d[+8]/*pointer to virtual method table of D (for B2)*/)[0]))(d+8) /* Call d->f2() */
    
    The call to d->f1() passes a B1 pointer as a parameter. The call to d->f2() passes a B2 pointer as a parameter. This second call requires a fixup to produce the correct pointer. It is impossible to call B2::f2 since it has been overridden in D's implementation. The location of B2::f2 is not in the vtable for D.
    
    By comparison, a call to d->f0() is much simpler:
    
    (*B1::f0)(d)
  • 相关阅读:
    我要变牛逼
    java web
    导师选择
    2.1进程
    来到博客园写东西的第一天
    简单的页面布局
    html5
    第一个servlet程序
    java2D
    字节流 文件字节流 缓冲字节流
  • 原文地址:https://www.cnblogs.com/autoria/p/6115985.html
Copyright © 2011-2022 走看看