FreeBASIC マニュアルのトップに戻る

FreeBASIC Virtual

目次→言語リファレンス→変数とデータ型→ユーザ定義型VIRTUAL←オリジナル・サイト

VIRTUAL


仮想メソッドを宣言します。

構文:
Type typename Extends base_typename
Declare Virtual Sub|Function|Property|Operator|Destructor ...
End Type

記述:
Virtual メソッドは、宣言された型から派生したデータ型によって上書きできるメソッドであり、動的な多態性(複数の型に属することを許す)を可能にします。
Abstract メソッドとは対照的に、仮想メソッドには実装が必要です。この実装は、仮想が上書きされていない場合に使われます。

派生型は、同じ識別子と署名、つまり同じ数と型のパラメータ(不変パラメータ)、同じ呼び出し規約、および、存在する場合は同じ戻り型(または参照またはポインタによる戻りのための共変戻り型)を持つ非静的メソッドを宣言することによって、基本型で宣言された仮想メソッドを上書きできます:
仮想メソッドであるという特性は、派生型の上書きメソッドによって黙示的に継承されることはありません。
この上書きメソッドを、下位レベルの派生型で上書きする必要がある場合は、仮想として宣言する必要があります。
一方、派生静的メソッドは、基本仮想/抽象メソッドを上書きできないため、署名に関係なく、同じ識別子を持つ任意の基本メソッド(仮想/抽象を含む)をシャドウすることができます。

仮想メソッドを呼び出すとき、コンパイラは、特定のオブジェクトに対して、呼び出すメソッドを調べるために vtable 検査を行う必要があります。
これには、追加の非表示の vtable ポインタ項目を、仮想メソッドを持つ各型の先頭に追加する必要があります。
この非表示の vptr は、組み込み Object 型によって提供されます。
このため、仮想メソッドは、直接的または間接的に extends Object 型の中でのみ、宣言できます。

上書き手続きを使った動的多型:

Constructors は仮想になりえません。Constructors は、特定の型を備えた、既存のオブジェクトを要求する仮想メソッドのオブジェクトを作成するからです。
呼ばれる構築子の型は、コードからのコンパイル時に決定されます。
さらに、構築子の内部の仮想メソッドを呼ぶとき、この構築子の型のオブジェクトと一致しているメソッドのバージョンだけが使われます。
これは、vptr は、派生型構築子によってまだ準備されず、ローカルの型構築子によってだけ準備されるからです。

Destructors は、多くの場合、 オブジェクトの基底型へのポインターによって操作されるオブジェクトを削除するとき、仮想であるに違いありません。 その結果、その破壊は、最も派生の型からスタートし、基底型まで進みます。
そのためには、明示的な破壊が必要とされていない場所に、空の本体を持つ仮想破壊子を追加して、コンパイラによって構築された、仮想ではない暗黙の破壊子に取って代わることが必要になるかもしれません。
一方、破壊子(仮想であるなしにかかわらず)内の仮想(または抽象)メソッドを呼ぶとき、この破壊子の型のオブジェクトに対応するメソッドのバージョンだけが使われます。
vptr が、それ自身の型の vtable に応た破壊子の一番上にリセットされるからです。
これは、子メソッドにアクセスすることを回避し、従って、先に子破壊子の実行によって破壊された子メンバーを参照することを回避します。

メンバーメソッドの宣言で Virtual を備えたメンバーメソッドのために、Virtual は、コードを読みやく改善するために、対応するメソッドの本体で指定することができます。

注意:
多重レベル継承では、同じ名前を付けられたメソッド(同じ識別子と署名)を、各継承階層レベルで、Abstract か、Virtual か、正常(指定子なし)、として宣言することができます。
指定子が混在している場合、通常、継承階層の優先順位は、abstract -> virtual -> normal の順です。
上書きメソッドのアクセス・コントロール(Public/Protected/Private)は、内部の多形性プロセスでは考慮されません。ただ、コンパイル時の最初の呼び出しのためにだけに使われます。
Base (member access).method() は、常にベース自身のメソッドを呼びます。上書きするメソッドではありません。

注: Virtual は、仮想/抽象メンバー手続きまたはメンバー演算子の vtable 内のインデックスを返すように Procptr に要求するための修飾子としても使われます。
Procptr ( identifier, Virtual [ Any|user_proctype ] )

例:
'' サブルーチンを上書きする例


Type Hello extends object
    Declare virtual Sub hi( )
End Type

Type HelloEnglish extends Hello
    Declare Sub hi( )            '' overriding subroutine
End Type

Type HelloFrench extends Hello
    Declare Sub hi( )            '' overriding subroutine
End Type

Type HelloGerman extends Hello
    Declare Sub hi( )            '' overriding subroutine
End Type


Sub Hello.hi( )
    Print "hi!"
    Sleep
End Sub

Sub HelloEnglish.hi( )            '' overriding subroutine
    Print "hello!"
    Sleep
End Sub

Sub HelloFrench.hi( )            '' overriding subroutine
    Print "Salut!"
    Sleep
End Sub

Sub HelloGerman.hi( )            '' overriding subroutine
    Print "Hallo!"
    Sleep
End Sub


    Randomize( Timer( ) )

    Dim As Hello Ptr h

    For i As Integer = 0 To 9
        Select Case( Int( Rnd( ) * 4 ) + 1 )
        Case 1
            h = New HelloEnglish
        Case 2
            h = New HelloFrench
        Case 3
            h = New HelloGerman
        Case Else
            h = New Hello
        End Select

        h->hi( )
        Delete h
    Next

Sleep


'' 破壊子を上書きし、
''              共変リターンを使って関数を上書きする例


Type myBase Extends Object
  Declare Virtual Function clone () As myBase Ptr
  Declare Virtual Sub Destroy ()
End Type

Function myBase.clone () As myBase Ptr
  Dim As myBase Ptr pp = New myBase(This)
  Print "myBase.clone() As myBase Ptr", pp
  Function = pp
End Function

Sub myBase.Destroy ()
  Print "myBase.Destroy()", , @This
  Delete @This
End Sub


Type myDerived Extends myBase
  Declare Function clone () As myDerived Ptr     '' 共変戻りでメンバー関数を上書きする
  Declare Sub Destroy ()                         '' overriding member subroutine
End Type

Function myDerived.clone () As myDerived Ptr     '' overriding member function with covariant return
  Dim As myDerived Ptr pc = New myDerived(This)
  Print "myDerived.clone() As myDerived Ptr", pc
  Function = pc
End Function

Sub myDerived.Destroy ()                         '' overriding member subroutine
  Print "myDerived.Destroy()", , @This
  Delete @This
End Sub


Dim As myDerived c

Dim As myBase Ptr ppc = @c
Dim As myDerived Ptr pcc = @c

Dim As myBase Ptr ppc1 = ppc->clone()            '' using base pointers and polymorphism
Dim As myDerived Ptr pcc1 = pcc->clone()         '' using derived pointers and covariance of return value
Print
ppc1->Destroy()                                  '' using base pointer and polymorphism
pcc1->Destroy()                                  '' using derived pointer

Sleep


方言差:

QBからの違い:

参照:
ユーザ定義型 に戻る
ページ歴史:2023-07-09 02:28:20
日本語翻訳:WATANABE Makoto、原文著作者:DkLwikki

ホームページのトップに戻る

表示-非営利-継承