FreeBASIC Virtual
目次→言語リファレンス→変数とデータ型→ユーザ定義型→VIRTUAL←オリジナル・サイト
VIRTUAL
仮想メソッドを宣言します。
構文:
記述:
Virtual メソッドは、宣言された型から派生したデータ型によって上書きできるメソッドであり、動的な多態性(複数の型に属することを許す)を可能にします。
Abstract メソッドとは対照的に、仮想メソッドには実装が必要です。この実装は、仮想が上書きされていない場合に使われます。
派生型は、同じ識別子と署名、つまり同じ数と型のパラメータ(不変パラメータ)、同じ呼び出し規約、および、存在する場合は同じ戻り型(または参照またはポインタによる戻りのための共変戻り型)を持つ非静的メソッドを宣言することによって、基本型で宣言された仮想メソッドを上書きできます:
- その差異が、パラメータ渡しモードまたは呼び出し規約または戻り型のみの場合は、コンパイル時に上書きエラーが返され、
- そうでなければ、両方のメソッドが多重定義できる(同じ型内で)場合に対応して、他の署名の違いに対して、シャドウイングだけが許可されます。
仮想メソッドであるという特性は、派生型の上書きメソッドによって黙示的に継承されることはありません。
この上書きメソッドを、下位レベルの派生型で上書きする必要がある場合は、仮想として宣言する必要があります。
一方、派生静的メソッドは、基本仮想/抽象メソッドを上書きできないため、署名に関係なく、同じ識別子を持つ任意の基本メソッド(仮想/抽象を含む)をシャドウすることができます。
仮想メソッドを呼び出すとき、コンパイラは、特定のオブジェクトに対して、呼び出すメソッドを調べるために vtable 検査を行う必要があります。
これには、追加の非表示の vtable ポインタ項目を、仮想メソッドを持つ各型の先頭に追加する必要があります。
この非表示の vptr は、組み込み
Object 型によって提供されます。
このため、仮想メソッドは、直接的または間接的に
extends Object 型の中でのみ、宣言できます。
上書き手続きを使った動的多型:
- 通常、typename から派生したオブジェクトを参照する場合でも、typename 手続き(または階層の上位)のみが、base-typename 参照/ポインタを通して、アクセスできます。
- しかし、手続きが仮想であるとき、これは実行中のプログラムに、参照/ポインターの生の基本型から通常はアクセス可能な手続きではなく、vtable 検査(実行時の動的バインディング)によって実際のオブジェクト型に関連して最も派生した上書き手続きを解決するように、指示します。(コンパイル時の静的バインディング)
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