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

📄 layout.txt

📁 开放源码的编译器open watcom 1.6.0版的源代码
💻 TXT
📖 第 1 页 / 共 2 页
字号:
- note: MicroSoft instead places a "construction displacement" following
        a virtual member
        - always uses the same VFPTR's
        - displacement is zero after construction
        - displacement added by all thunks
        - displacement is non-zero during construction

- note: Borland (2.0) compiles code to do a "new" when the "this" pointer
        is passed as 0. When the "new" fails, nothing happens. The address
        of the object is always returned.

Constructor Displacements (justification)
========================

- eliminate the need for virtual function tables and/or thunks that might be
  required only during construction:

  class V { virtual void f(); virtual void g(); }
  class A : public virtual V { virtual void f() };
  class B : public A { virtual void g(); int b1; };

  - allocated as (if no constructor displacement for V): (V_A, V_B are offsets
    of V when A, B allocated, respectively)

          B               A
        ===========     ============
        vfptr(A)        vfptr(A)
        vbptr(A)        vbptr(A)
        b1          V_A:vfptr(V)
    V_B:vfptr(V)

  - during V construction:

    (1) vfptr(V)   V.f, V.g

  - during and after A construction (if A created)

    (2) vfptr(A)   A.f, t(A)_V.g ( this += V_A; goto V.g )
    (3) vfptr(V)   t(V)_A.f ( this -= V_A; goto A.f ), V.g

  - during A construction (if B created)

    (4) vfptr(A)   A.f, t(A)_V.g ( this += V_B; goto V.g )
    (5) vfptr(V)   t(V)_A.f ( this -= V_B; goto A.f ), V.g

        note: these two virtual function tables are required only during
              construction

    (4) & (2) can be the same, if virtual base table is used:

    (2) vfptr(A)   A.f, t(A)_V.g ( this += offset(vbptr)
                                           + this->vbptr->offset_A; goto V.g )

  - during and after B construction (if B created)

    (6) vfptr(A)   A.f, B.g
    (7) vfptr(V)   t_V_B_f ( this -= V_B; goto A.f ),
                   t_V_B_g ( this -= V_B; goto B.g )

  - Borland (2.0) defines all the tables as shown

        - this will be expensive when there is lots of virtual inheritance,
          as each virtual derived inheritance will require separate tables
          for its virtual bases (order nxn tables with n inheritance levels)

  - MicroSoft introduces a constructor-delta (stored as the last a member
    of V) in order that only one version of tables (3) and (5) need be
    constructed:

    (3) V:  vfptr   T(V)_A.f ( this -= V_A+con_delta(V); goto A.f ), V.g

    - con_disp's are always zero after construction

    - while constructing A (standalone), con_disp(V) is zero

    - while constructing A (in B), con_disp(V) is set to be ( V_B - V_A ), the
      difference between the location of V in the standalone version and in
      the containment version


Rules: virtual base tables
==========================

- used in code and thunks when converting "this-derived" to
  "this-virtual-base"

- can use a VBPTR in a non-virtual base class if one exists; otherwise, one
  is required for current class

- a virtual base table can be uniquely named using the name of the
  allocating class and of the class containing the VFPTR


Rules: virtual function tables
==============================

- always used to call a virtual function

- if class defines virtual functions, it requires a table

- if class inherits virtual functions from a virtual base, it requires a table

- if class inherits virtual functions from a non-virtual base whose "this"
  differs from the "this" for the class, it requires a table

- if class inherits from multiple bases with different function ordering,
  a table is required

- a virtual function table can be uniquely named using the name of the
  allocating class and of the class containing the VFPTR


Additional Ambiguities
======================

- the compiler needs to detect ambiguities during creation of virtual
  function tables:

        class A { virtual void f(); };
        class B { virtual void f(); };
        class C : public virtual A, public virtual B { };

  - here f() is ambiguous for class C, even though no functions in C
    reference f()
  - this needs to be detected when the C scope is closed

Rules: thunks
=============

- required as an intermediary to a function when the "this" pointer must
  be converted

- conversion to non-virtual base: adjust by offset

- conversion to derived from non-virtual base; adjust by offset

- conversion to virtual base: use a VBPTR to determine adjustment

- conversion to derived from virtual base: subtract sum of construction
  displacement of base + constant difference between classes

- a thunk can be uniquely named using the names of the function, the class
  containing the VFPTR, and of the allocating class.


Numbering virtual functions
===========================

- each virtual function is assigned a unique index to be translated into an
  offset in the virtual functions table

- for such function (derived or defined), the VFPTR to be used must be
  chosen
    - if the function exists in the associated table, then, the number
      already assigned is used; otherwise, the table is to be extended
      by one entry and the next number for that table is used
    - a new function is assigned to the leftmost table

Numbering virtual bases
=======================

- the virtual bases must also be assigned a unique order

- for such a base, the VBPTR to be used must be chosen
    - if the base exists in the associated table, then, the number
      already assigned is used; otherwise, the table is to be extended
      by one entry and the next number for that table is used
    - a new function is assigned to the leftmost table

Generation of virtual tables
============================

- bit associated with each class indicates if data-generation of virtual
  function tables and virtual base tables for the class have been completed

- the current class is called sclass (source class)

- internal names of thunks and virtual tables are kept in file scope
    - when a name needs to be added, the data (if required) for the table
      is also generated
    - when a new thunk name is used, the code for that name is generated
      as a separate "procedure"

- normally tables and thunks are generated as local statics
    - proposed #pragma support may modify this behavior
        #pragma class name static   ( generate data/thunks as static )
        #pragma class name extern   ( reference data/thunks externally )
        #pragma class name public   ( generate data/thunks as public )
??????  #pragma class name common   ( generate data/thunks as public/common )
        - "name" indicates name of class to be handled as above
        - "*" for "name" sets defaults
        - this allows home modules for classes

- generate name for virtual base table using (sclass, bclass) where bclass
  is the class name containing the VBPTR
    - for all VFPTRS in class and base classes
        - generate label for the function table using (sclass, fclass) where
          fclass is name of class containing the VFPTR
        - for a virtual function table to be generated (if not external name)
            - generate the label
        - for the virtual functions, in order
            - detect ambiguity if present !!!!!!!!!!!!!!!!!!!
            - tclass is the class containing the function
            - compute "this" adjustment required
            - if adjustment is zero
                - generate addr(function)
              else
                - generate a thunk-name from( tclass, function, adjustment )
                  if adjustment does not cross a virtual boundary
                - generate a thunk-name from( tclass, function, vclass ) where
                  vclass is least-derived class with same "this" as sclass
                  which can access the VBPTR used in the thunk, when sclass
                  and tclass are separated by a virtual boundary
                - generate addr( thunk name )
                - if a newly defined thunk, generate the thunk
Thunk Generation
================

- thunks are generated as follows:

    thunk( tclass, function, adjustment )   [ adjustment not virtual ]
        this += adjustment or this -= adjustment
        goto tclass.function

    thunk( tclass, function, vclass )       [ tclass is base of vclass ]
        temp = this->vclass.vbptr
        this = temp + temp->offset_function
        goto tclass.function

    thunk( tclass, function, vclass )       [ vclass is base of tclass ]
        this -= offset + this->cons_disp_vclass
        goto tclass.function

Differences between Borland(doc'd) and MicroSoft
================================================

- this section written from Borland point of view

- stores pointer (16-bit offset for "this") at location that virtual class
  object would be allocated, if the class were not virtual

- stores construction displacement before (not after) virtual members

- adds extra pointers to virtual base classes to ensure at most one level
  of computation to cast a "this" to a virtual base

- minimum class object size is always 1 byte

- can declare classes to be near or far

- can declare classes to be _export

- constructors passed 0 as "this" will use "new" to allocate object
    - "this" returned by constructors
    - constructors with virtual bases are passed a flag int
        0 ==> construct virtuals bases

- destructors always passed extra int flag of bits:
    x'01' ==> call delete for object
    x'02' ==> destruct virtual classes

- name mangling is different

⌨️ 快捷键说明

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