目次→
演算子→
ポインタ演算子→
Operator PROCPTR (Procedure pointer and vtable index)←オリジナル・サイト
任意の手続きのアドレスと、仮想/抽象メンバ手続きの vtable 内のインデックスを返します。
構文:
用法:
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 を記述できるようにするだけです。)
記述:
最初の構文:
- この演算子は、
Sub か
Function の静的/メンバー手続きまたはメンバー演算子の、アドレスを返します。
- 戻り値の型は、手続きの内部署名 (ユーザー署名、およびメンバ手続きの補足的な最初のパラメータ
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
バージョン:
- fbc 1.10.0 より前は、メンバー手続き/演算子はサポートされていませんでした。
- fbc 1.09.0 より前は、2番目の引数(オプション)はサポートされていませんでした。
方言差:
-
別名 __Procptr と共に参照をつけないと、-lang qb 方言で利用できません。
QBからの違い:
参照: