Core C++

6.3. Inheritance🔗

Definition6.3.1
Group: Abstract data types, objects, classes and inheritance. (11)
Group member previews
Preview
Definition 6.1.1
Loading preview
Group member preview content is loaded from the rendered-fragment cache.
Statement uses 2
Statement dependency previews
Preview
Definition 2.2.1
Loading preview
Statement dependency preview content is loaded from the rendered-fragment cache.
Used by 2
Reverse dependency previews
Preview
Definition 6.3.2
Loading preview
Reverse dependency preview content is loaded from the rendered-fragment cache.
✓L∃∀N

A pointer to a derived class is accepted where a pointer to its base is expected, in declarations, assignments, arguments, returns, comparisons and the branches of ?:. It is the only conversion between class types, and the other direction is a type error.

\dfrac{D \text{ derives from } B}{D* \approx B*}\;\textsf{(Subsumption)}

Lean code for Definition6.3.1●3 definitions
  • defdefined in CoreCpp/Typing.lean
    complete
    def CoreCpp.Typing.compat (p : CoreCpp.Program) :
      CoreCpp.Ty → CoreCpp.Ty → Bool
    def CoreCpp.Typing.compat
      (p : CoreCpp.Program) :
      CoreCpp.Ty → CoreCpp.Ty → Bool
    τ ≈ τ', the type τ of a value is accepted where τ' is expected. Equal
    types, nullptr against a pointer type, or, by subsumption, a pointer to a
    derived class where a pointer to its base is expected. These and the lambda
    to `std::function` are the only implicit conversions.
    
    ```
    D derives from B
    ──────────────── (Subsumption)
    D* ≈ B*
    ```
    
    ```
    Γ ⊢ e : D*    D derives from B
    ────────────────────────────── (T-Sub)      subsumption where a value is
    Γ ⊢ e : B*                                  used, wherever ≈ is required
    ```
    
  • defdefined in CoreCpp/Syntax.lean
    complete
    def CoreCpp.Program.subclass (p : CoreCpp.Program) (d c : String) : Bool
    def CoreCpp.Program.subclass
      (p : CoreCpp.Program) (d c : String) :
      Bool
    d is c or derives from c. 
Definition6.3.2
Group: Abstract data types, objects, classes and inheritance. (11)
Group member previews
Preview
Definition 6.1.1
Loading preview
Group member preview content is loaded from the rendered-fragment cache.
Statement uses 3
Statement dependency previews
Preview
Definition 2.1.11
Loading preview
Statement dependency preview content is loaded from the rendered-fragment cache.
Used by 3
Reverse dependency previews
Preview
Definition 6.2.3
Loading preview
Reverse dependency preview content is loaded from the rendered-fragment cache.
✓L∃∀N

A virtual method is chosen by the class tag T of the receiver, the nearest declaration in the chain of T, so a call through a base pointer reaches the override of the derived class. A non virtual method is chosen by the static class S.

A derived class redefines only a method the base declares virtual, and marks it override, so the method reached from S and the one reached from T coincide for every non virtual method.

Redefining a non virtual method, marking override without a virtual method in a base, or changing the signature is a type error.

Some of the implementations are partial, so Lean records opaque constants that carry the type and not the body, and no property of them is proved here.

Lean code for Definition6.3.2●3 definitions
  • defdefined in CoreCpp/Eval.lean
    complete
    def CoreCpp.Eval.resolve (fs : CoreCpp.FunEnv) (s t m : String)
      (sig : Option (List CoreCpp.Ty)) : CoreCpp.M (CoreCpp.Method × String)
    def CoreCpp.Eval.resolve (fs : CoreCpp.FunEnv)
      (s t m : String)
      (sig : Option (List CoreCpp.Ty)) :
      CoreCpp.M (CoreCpp.Method × String)
    The method m of class s with the signature the type checker chose, the
    nearest in the chain of s, dispatched by the tag t when that method is
    virtual. The signature picks one member of an overload set, and without it,
    in an unannotated program, the first of the name serves. 
  • defdefined in CoreCpp/Syntax.lean
    complete
    def CoreCpp.Program.findMethod (p : CoreCpp.Program) (c m : String) :
      Option (CoreCpp.Method × String)
    def CoreCpp.Program.findMethod
      (p : CoreCpp.Program) (c m : String) :
      Option (CoreCpp.Method × String)
    The method m as seen from class c, the nearest declaration in the chain,
    with the class that declares it. With m overloaded it is the first of the
    overload set, and `findMethods` gives them all. 
  • defdefined in CoreCpp/Typing.lean
    complete
    def CoreCpp.Typing.cls (p : CoreCpp.Program) (c : CoreCpp.ClassDecl) :
      CoreCpp.T Unit
    def CoreCpp.Typing.cls (p : CoreCpp.Program)
      (c : CoreCpp.ClassDecl) : CoreCpp.T Unit
    A class is well formed when the conditions below hold.
    
    Its base exists and the chain of bases has no cycle. Its fields have types
    that carry values, are themselves well formed, and repeat no field of a base.
    
    Its members have distinct names, and each method redefines only a method the
    base declares virtual, carrying override and the same signature. The
    constructor of the base, if the base has one, takes no parameters.
    
    Every member body is well typed under `this`.
    
    ```
    B exists, chain acyclic    fields storable, well formed, new in the chain
    for each method m of C. if some base has m then that m is virtual,
        m is override and the signatures agree
    for each override m of C. some base has a virtual m
    B has no constructor or one with no parameters
    [this ↦ C*, params] ⊢ body ⊣ Γ' for each member body
    ──────────────────────────────────────────────────────────────── (T-Class)
    ⊢ class C : public B { … }
    ```
    
Theorem6.3.3
Group: Abstract data types, objects, classes and inheritance. (11)
Group member previews
Preview
Definition 6.1.1
Loading preview
Group member preview content is loaded from the rendered-fragment cache.
Statement uses 2
Statement dependency previews
Preview
Definition 6.2.3
Loading preview
Statement dependency preview content is loaded from the rendered-fragment cache.
used by 0XL∃∀N

For every well typed program, the method a call resolves to by the static class of the receiver and the method it resolves to by the class tag coincide whenever the method is not virtual.

The nearest declaration of a non virtual m from S is also the nearest from T, because no class between T and S redeclares m. There is no Lean proof, the property follows from the rule T-Class by inspection.

Definition6.3.4
Group: Abstract data types, objects, classes and inheritance. (11)
Group member previews
Preview
Definition 6.1.1
Loading preview
Group member preview content is loaded from the rendered-fragment cache.
Statement uses 6
Statement dependency previews
Preview
Definition 2.1.5
Loading preview
Statement dependency preview content is loaded from the rendered-fragment cache.
used by 1✓L∃∀N

The command delete e applies to a pointer to a class or to an object type of the library, whose rule DeleteLib is in Definition 8.1.2.

On an object it runs the destructors of the chain from the tag up to the root, each with this bound to the object, and removes the record and the field locations from \sigma.

A second delete, a delete through a pointer to a base without a virtual destructor in its chain, and any later access are error, the three cases C++17 leaves undefined. delete nullptr does nothing, as in C++.

\dfrac{\Gamma \vdash e : C*}{\Gamma \vdash \mathtt{delete}\ e \dashv \Gamma}\;\textsf{(T-Delete)}

\dfrac{\Gamma \vdash e : L\langle\bar{\tau}\rangle* \qquad L\langle\bar{\tau}\rangle \text{ an object type} \qquad \Gamma \vdash_L \mathtt{delete} : \to \mathsf{void}}{\Gamma \vdash \mathtt{delete}\ e \dashv \Gamma}\;\textsf{(T-DeleteLib)}

\dfrac{\begin{array}{c} \rho, \sigma \vdash e \Rightarrow \mathsf{loc}\,\ell, \sigma_0\qquad \sigma_0(\ell) = \mathsf{obj}\,T\,[f_1 \mapsto \ell_1, \ldots, f_n \mapsto \ell_n] \\ S \text{ the static class of } e\qquad S = T \text{ or the chain of } S \text{ has a virtual destructor} \\ \text{the destructors of the chain of } T \text{ run from } T \text{ up, giving } \sigma_1 \end{array}}{\rho, \sigma \vdash \mathtt{delete}\ e \Rightarrow \mathsf{normal}, \rho, \sigma_1 \setminus \{\ell, \ell_1, \ldots, \ell_n\}}\;\textsf{(Delete)}

\dfrac{\rho, \sigma \vdash e \Rightarrow \mathsf{null}, \sigma_0}{\rho, \sigma \vdash \mathtt{delete}\ e \Rightarrow \mathsf{normal}, \rho, \sigma_0}\;\textsf{(DeleteNull)}

Some of the implementations are partial, so Lean records opaque constants that carry the type and not the body, and no property of them is proved here.

Lean code for Definition6.3.4●3 definitions
  • opaquedefined in CoreCpp/Typing.lean
    complete
    opaque CoreCpp.Typing.cmd (p : CoreCpp.Program) (τᵣ : CoreCpp.Ty)
      (Γ : CoreCpp.TEnv) : CoreCpp.Cmd → CoreCpp.T CoreCpp.TEnv
    opaque CoreCpp.Typing.cmd (p : CoreCpp.Program)
      (τᵣ : CoreCpp.Ty) (Γ : CoreCpp.TEnv) :
      CoreCpp.Cmd → CoreCpp.T CoreCpp.TEnv
    Γ ⊢ c ⊣ Γ', under the return type τᵣ of the enclosing function. 
  • opaquedefined in CoreCpp/Eval.lean
    complete
    opaque CoreCpp.Eval.cmd (fs : CoreCpp.FunEnv) (ρ : CoreCpp.Env)
      (σ : CoreCpp.Store) (c : CoreCpp.Cmd) :
      CoreCpp.M (CoreCpp.Ctrl × CoreCpp.Env × CoreCpp.Store)
    opaque CoreCpp.Eval.cmd (fs : CoreCpp.FunEnv)
      (ρ : CoreCpp.Env) (σ : CoreCpp.Store)
      (c : CoreCpp.Cmd) :
      CoreCpp.M
        (CoreCpp.Ctrl ×
          CoreCpp.Env × CoreCpp.Store)
    ρ, σ ⊢ c ⇒ r, ρ', σ' 
  • defdefined in CoreCpp/Syntax.lean
    complete
    def CoreCpp.Program.hasVirtualDtor (p : CoreCpp.Program) (c : String) : Bool
    def CoreCpp.Program.hasVirtualDtor
      (p : CoreCpp.Program) (c : String) :
      Bool
    Some class in the chain of c declares a virtual destructor, so `delete`
    through a pointer to c reaches the destructor of the tag.