⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 layout.txt

📁 开放源码的编译器open watcom 1.6.0版的源代码
💻 TXT
📖 第 1 页 / 共 2 页
字号:
Class Layout
============

This document details how a class is laid out in memory. Unless noted, the
design follows the MicroSoft specification document.

- related documents:
    - CTORDTOR.TXT: discusses constructors, destructors, error handling


History
-------

91/11/21 -- JWW     - initial version


Layout
======

- a class object is allocated as follows (each section is optional and will
  be allocated only if required):

    (a) VFPTR - pointer to virtual functions table
        - this is a list of function/thunk pointers

    (b) VBPTR - pointer to virtual bases table
        - this is a list of offsets to be added to the "this" pointer in order
          to access a virtual base object

    (c) any non-virtual base objects with virtual functions
        - occur (recursively) in order of definition

    (d) any non-virtual base objects without virtual functions
        - occur (recursively) in order of definition
        - this gives better addressing on first such object

    (e) data members of the class
        - occur in order of definition

  - the virtual base objects of an object occur following all non-virtual
    objects
    - each object is followed by a "construction-displacement" offset when the
      class has virtual functions

  - data members and class objects are aligned as required

  - an empty class object requires one byte of storage when it is immediately
    followed by an empty class of the same type

- example:                                                   A
                                                            /
    class A { a1; a2; };                                   /
    class B : public A { b1; b2; };                 A     B
    class C : public A, public B { c1; c2; };        \   /
                                                      \ /
    - laid out as:                                     C

        - storage for C::A
            - C::A.a1
            - C::A.a2

        - storage for C::B
            - storage for C::B::A
                - C::B::A.a1
                - C::B::A.a2
            - A::B.b1
            - A::B.b2

        - storage for C
            - C::c1
            - C::c2


- example:  (only data members shown)                          A (virtual)
                                                               |\
    class A { a1; a2; };                                       | \
    class B : public virtual A { b1; b2; };                    |  B
    class C : public virtual A, public B { c1; c2; };          | /
                                                               |/
    - laid out as:                                             C

        - storage for C::B
            - A::B.b1
            - A::B.b2

        - storage for C
            - C::c1
            - C::c2

        - storage for C::A (virtual)
            - C::A.a1
            - C::A.a2

Virtual Base Tables
===================

- virtual bases exist because the virtual classes do not occur at
  fixed offsets from a derived class

- a "virtual base pointer" (VBPTR) is used to point at a table of
  offsets to establish the location of base classes
    - allocated in self unless allocated in non-virtual base class
    - offsets are relative to the VBPTR

- access to a virtual base class is accomplished by:

      table = this_derived->vbptr;
      this_base = this_derived + vbptr + table->offset_base;

    - offsets are not relative to the "this" pointer so that more sharing
      of VBPTR's can be possible

- thus, we need to construct the follow parse-tree when converting to a
  virtual base

                VBPTR
               / \
              /   \
             *     type-list (virtual-class)
            /
           /
         this

- we need support to supply offsets of VBPTR and class-offset for a
  <derived,virtual> combination

- in general, virtual base tables are used to access virtual base class
  objects, from compiled code and from thunks (described later)

- optimization: if the exact type of an object is known, then direct
                addressing can be used, since the location of all class
                objects will be known.

Virtual Function Tables
=======================

- operate similarily to Virtual Base Tables, except are used to access tables
  of addresses of virtual functions

- a "virtual function pointer" (VFPTR) is used to point at a table of
  function addresses
    - allocated in self, unless allocated in a non-virtual base class

- example: (assume all functions are virtual)

        class A { f(); g() };
        class B : public virtual A { f(); h(); };
        class C : public virtual A { g(); h(); };
        class D : public B, public C { f(); g(); h(); };



              A { f(); g() };
             / \
            /   \
           /     \
          /       \
         /         \
  B { f(); h() }    C { g(); h(); }
         \         /
          \       /
           \     /
            \   /
             \ /
              D { f(); g(); h() };

    - the following virtual function tables exist in A,B,C,D when each,
      respectively, is the allocated class
        VFT_A : { A.f, A.g }
        VFT_B : { B.f, t(B)_A.g, B.h }
        VFT_C : { t(C)_A.f, C.g, C.h }
        VFT_D : { D.f, D.g, D.h }

    - t(C1)_C2.f is a "thunk" from class C1 to a function f in class C2

- optimization: if the exact type of an object is known, then the functions
                or appropriate thunk, can be directly called, since the
                appropriate function to be invoked can be determined from
                the information in the symbol table

Thunks
======

    - notation t(C1)_C2.fun is for a "thunk" routine (generated whenever
      an adjustment to the "this" pointer is required); for example:

        this_C2 += offset(C2)-offset(C1)
        goto fun;

        - this can be compiled since offset(C1) and offset(C2) are known
          when a class object is allocated; offset(C) is the offset of the C
          object from the start of the allocated object

        - note: need support for this from code-generator
            - thunk must not change anything except "this"
            - thunk must allow arbitrary return

        - note: optimization - pragma support to avoid duplicate thunks
            - this is the same optimization as is required for virtual
              tables in general (normally they are (static, public, extern)
              code when tables are correspondingly (static, public, extern).

        - note: optimization for space - generate thunks using call to
                generated this-conversion routines, when warranted

    - when a D is allocated
        - storage for D
            - storage for D::B
                - VFPTR --> VFT_B_D = { D.f, D.h }
                - VBPTR --> VBT_B_D = { offset(D::B::A) }
            - storage for D::C
                - VFPTR --> VFT_A_D = { t(C)_D.f, t(C)_D.g, t(C)_D.h }
                - VBPTR --> VBT_A_D = { offset(D::B::A) - offset(D::C) }

        - storage for D::B::A   (virtual)
            - VFPTR --> VFT_A_D = { t(A)_D.f, t(A)_D.g }
            - con_disp_A

        t(C)_D.f( this_C ) : D.f( this_C + offset( D::B::A ) )
        t(C)_D.g( this_C ) : D.g( this_C + offset( D::B::A ) )
        t(C)_D.h( this_C ) : D.h( this_C + offset( D::B::A ) )
        t(A)_D.f( this_A ) : D.f( this_A - this_A->con_disp_A
                                  - offset( D::B::A ) )
        t(A)_D.g( this_A ) : D.g( this_A - this_A->con_disp_A
                                  - offset( D::B::A ) )


    - when a C is allocated
        - storage for D::C
            - VFPTR --> VFT_C   = { t(C)_A.f, C.g, C.h }
            - VBPTR --> { offset(C::A) }

        - storage for C::A      (virtual)
            - VFPTR --> VFT_A_C = { A.f, t(A)_C.g, t(A)_C.h }

        t(C)_A.f( this_C ) : D.f( this_C + offset( C::A ) )
        t(A)_C.g( this_A ) : D.g( this_A - this_A->con_disp_A
                                  - offset( C::A ) )
        t(A)_C.h( this_A ) : D.h( this_A - this_A->con_disp_A
                                  - offset( C::A ) )


                VFPTR
               / \
              /   \
             *     type-list (virtual-class)
            /
           /
         this

- we need support to supply offsets of VFPTR and member-function-offset for a
  <derived,function> combination


Constructors/Destructors
========================

- require that their own virtual functions are called when they are active
- a constructor must set its own VFPTR in self and all base classes, after
  the base classes and members of the class have been constructed
- a destructor must set its own VFPTR in self and all base classes, before
  execution of the destructor body.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -