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

FreeBASIC OpProcptr

目次演算子ポインタ演算子Operator PROCPTR (Procedure pointer and vtable index)←オリジナル・サイト

演算子 PROCPTR (手続きポインタと vtable索引) 左にメニュー・フレームが表示されていない場合は、ここをクリックして下さい


任意の手続きのアドレスと、仮想/抽象メンバ手続きの vtable 内のインデックスを返します。

構文:
declare 演算子 Procptr ( byref identifier as proctype [, any|user_proctype ] ) as internal_proctype ptr
declare 演算子 Procptr ( byref identifier as proctype, virtual [ any|user_proctype ] ) as integer

用法:
result = Procptr ( identifier [, [virtual] [any|user_proctype] ] )

パラメタ:
identifier
手続き識別子
user_proctype
手続きのあらゆるユーザ型 (sub/function, static/member, normal/virtual).
(internal_proctype は、UDT udt_name のメンバー手続きに対してのみ、補助的な第一引数 byref as udt_name があります))

戻り値:
(最初の構文)任意の手続きのアドレス を、または (修飾子 virtual を付加した 2 番目の構文) 仮想/抽象メンバー 手続きの vtable 内のインデックスを返します。
(any、つまり、任意の手続きの署名は、(使用しない場合と比較して)特定の選択を誘発するものではなく、常に 2 つの引数を指定して Procptr を記述できるようにするだけです。)

記述:
最初の構文:
- この演算子は、SubFunction の静的/メンバー手続きまたはメンバー演算子の、アドレスを返します。
- 戻り値の型は、手続きの内部署名 (ユーザー署名、およびメンバ手続きの補足的な最初のパラメータ byref as udt_name) に一致します。
2 番目の構文 (修飾子 virtual を使用):
- この演算子は、仮想/抽象メンバー手続きまたはメンバー演算子の vtable 内のゼロから始まるインデックスを返します。
- 上書きされたメンバー手続き (ポリモーフィズム) の場合、vtable インデックスにより、使用されるインスタンスの vtable から、クラス階層内で最も下位のクラスで派生した上書きメンバー手続きのアドレスへのアクセスが可能になります。

user_proctype 引数を使う場合、Procptr 構文では、パラメーターの型 (サブ/関数の型と、存在する場合戻り値の型を含む) に基づいて手続きポインターまたは vtable インデックスを取得できます。
これにより、手続きの多重定義を解決するための適切な手続きを明示的に指定したり、多重定義されていない手続きのパラメータの型 (サブ/関数の型や戻り値の型を含む) をチェックしたりすることができます。

演算子 @ (のアドレス) を手続きで使うと、2 番目の引数のない最初の Procptr 構文と同じように動作します。

注意:
- 手続きメンバーが抽象の場合、 Procptr ( identifier [, any|user_proctype ] ) は、メンバー手続き呼び出し署名 (internal_proctype) の null 手続きポインタを返します。
- vtable エントリがない (または vtable がまったくない) 場合、Procptr ( identifier , virtual [any|user_proctype] ) は特別な値 -1 を返します。

例:
' この例は、ProcPtr を使って、関数ポインタをデモします
Declare Function Subtract( x As Integer, y As Integer) As Integer
Declare Function Add( x As Integer, y As Integer) As Integer
Dim myFunction As Function( x As Integer, y As Integer) As Integer

' myFunction は、今、Add に割り当てられます
myFunction = ProcPtr ( Add )
Print myFunction (2, 3)

' myFunction は、今、Subtract に割り当てられます。
' 出力が変わることに、注意してください。

myFunction = ProcPtr ( Subtract )
Print myFunction (2, 3)

Function Add( x As Integer, y As Integer) As Integer
    Return x + y
End Function

Function Subtract( x As Integer, y As Integer) As Integer
    Return x - y
End Function

Sleep


Sub s Overload()
End Sub

Sub s( ByVal i As Integer )
End Sub

'----- fbc 1.09.0 〜、ProcPtr は 2番目のパラメーター(オプション)をサポートします:
Var s1 = ProcPtr( s, Sub() )
Var s2 = ProcPtr( s, Sub( ByVal i As Integer ) )

'----- fbc 1.09.0 より前は、次の場合のみ可能でした:
'Dim s1 As Sub()
's1 = ProcPtr( s )
'Dim s2 As Sub( Byval i As Integer)
's2 = ProcPtr( s )


' fbc 1.10.0 以降、ProcPtr は様々な構文のメンバ手続き/演算子をサポートしています。

Type UDT Extends Object
    Dim As String s1
    Dim As String s2
    Declare Virtual Sub test()
    Declare Virtual Operator Cast() As String
End Type

Sub UDT.test()
    Print This.s1
End Sub

Operator UDT.Cast() As String
    Return This.s2
End Operator

Var testPtr1 = ProcPtr(UDT.test)
Var testPtr2 = ProcPtr(UDT.test, Any)
Var testPtr3 = ProcPtr(UDT.test, Sub())

Dim As Function(ByRef As UDT) As String castPtr1 = ProcPtr(UDT.Cast)
Dim As Function(ByRef As UDT) As String castPtr2 = ProcPtr(UDT.Cast, Any)
Dim As Function(ByRef As UDT) As String castPtr3 =  ProcPtr(UDT.Cast, Function() As String)

Var testIndex1 = ProcPtr(UDT.test, Virtual)
Var testIndex2 = ProcPtr(UDT.test, Virtual Any)
Var testIndex3 = ProcPtr(UDT.test, Virtual Sub())

Dim As Integer castIndex1 = ProcPtr(UDT.Cast, Virtual)
Dim As Integer castIndex2 = ProcPtr(UDT.Cast, Virtual Any)
Dim As Integer castIndex3 = ProcPtr(UDT.Cast, Virtual Function() As String)

Print testPtr1  '' UDT.test ポインタの絶対アドレス値
Print testPtr2  '' absolue address value of UDT.test pointer
Print testPtr3  '' absolue address value of UDT.test pointer
Print

Print castPtr1  '' UDT.Cast ポインタの絶対アドレス値
Print castPtr2  '' absolue address value of UDT.Cast pointer
Print castPtr3  '' absolue address value of UDT.Cast pointer
Print

Print testIndex1  '' UDT.test の vtable インデックス
Print testIndex2  '' vtable index of UDT.test
Print testIndex3  '' vtable index of UDT.test
Print

Print castIndex1  '' UDT.Cast の vtable インデックス
Print castIndex2  '' vtable index of UDT.Cast
Print castIndex3  '' vtable index of UDT.Cast
Print

Dim As UDT u
u.s1 = "Virtual Sub test()"
u.s2 = "Virtual Operator Cast() As String"

testPtr1(u)  '' 手続きポインタを介して u.test() を実行する
testPtr2(u)  '' execute u.test() through its procedure pointer
testPtr3(u)  '' execute u.test() through its procedure pointer
Print

Print castPtr1(u)  '' 手続きポインタを介して Cast(UDT, u) を実行する
Print castPtr2(u)  '' execute Cast(UDT, u) through its procedure pointer
Print castPtr3(u)  '' execute Cast(UDT, u) through its procedure pointer
Print

CPtr(Sub(ByRef As UDT), CPtr(Any Ptr Ptr Ptr, @u)[0][testIndex1])(u)  '' vtable インデックスを介して u.test() を実行する
CPtr(Sub(ByRef As UDT), CPtr(Any Ptr Ptr Ptr, @u)[0][testIndex2])(u)  '' execute u.test() through its vtable index
CPtr(Sub(ByRef As UDT), CPtr(Any Ptr Ptr Ptr, @u)[0][testIndex3])(u)  '' execute u.test() through its vtable index
Print

Print CPtr(Function(ByRef As UDT) As String, CPtr(Any Ptr Ptr Ptr, @u)[0][castIndex1])(u)  '' vtable インデックスを介して Cast(UDT, u) を実行する
Print CPtr(Function(ByRef As UDT) As String, CPtr(Any Ptr Ptr Ptr, @u)[0][castIndex2])(u)  '' execute Cast(UDT, u) through its vtable index
Print CPtr(Function(ByRef As UDT) As String, CPtr(Any Ptr Ptr Ptr, @u)[0][castIndex3])(u)  '' execute Cast(UDT, u) through its vtable index
Print

Sleep

' fbc 1.10.0以降、ProcPtr は、仮想/抽象メンバ手続き/演算子の vtable インデックスへのアクセスも可能にしました。

Type Parent Extends Object
    Declare Abstract Sub VirtualTest()
    Declare Virtual Operator Cast() As String
    Declare Sub NormalTest()
End Type

Operator Parent.Cast() As String
    Return "Parent.Cast() As String"
End Operator

Sub Parent.NormalTest()
    Print "Parent.NormalTest()"
End Sub

Type Child Extends Parent
    Declare Virtual Sub VirtualTest()          '' or Declare Sub test()
    Declare Virtual Operator Cast() As String  '' or Declare Operator Cast() As String
    Declare Sub NormalTest()
End Type

Sub Child.VirtualTest()
    Print "Child.VirtualTest"
End Sub

Operator Child.Cast() As String
    Return "Child.Cast() As String"
End Operator

Sub Child.NormalTest()
    Print "Child.NormalTest()"
End Sub

Dim As Parent Ptr p = New Child

(*p).VirtualTest()      '' or p->VirtualTest()
Print Cast(Parent, *p)  '' or Print *p
(*p).NormalTest()       '' or p->NormalTest()
Print

#define RuntimeProcPtr(instance, procedure, signature...) _   '' pointer to procedure
    __FB_IIF__(ProcPtr(procedure, Virtual signature) >= 0, _  '' (the most derived override if exists)
               CPtr(TypeOf(ProcPtr(procedure, signature)), _
                    CPtr(Any Ptr Ptr Ptr, @(instance)) _
                    [0][ProcPtr(procedure, Virtual signature)]), _
               ProcPtr(procedure, signature))

'' ここでは、マクロに手続き署名を提供しても役に立ちません。
'' (この場合、解決すべき手続きの多重定義がないためです)
RuntimeProcPtr(*p, Parent.VirtualTest)(*p)  '' vtable インデックスを介して (*p).VirtualTest() を実行します
Print RuntimeProcPtr(*p, Parent.Cast)(*p)   '' vtable インデックスを介して Cast(Parent, *p) を実行します
RuntimeProcPtr(*p, Parent.NormalTest)(*p)   '' コンパイル アドレスを通して (*p).NormalTest() を実行します
Print

Delete p
Sleep


バージョン: 方言差:
QBからの違い:
参照:
ポインタ演算子 に戻る
演算子 に戻る
←リンク元に戻る プログラム開発関連に戻る
ページ歴史:2024-03-02 13:30:25
日本語翻訳:WATANABE Makoto、原文著作者:LaananFisher

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

表示-非営利-継承