过程指针
- 来源: https://www.freebasic.net/wiki/wikka.php?wakka=ProPgProcedurePointers
- 最后更新: 2024-02-15
指向过程的指针
就像指针可以指向 Integer 或 Single 类型一样,指针也可以指向过程,即它们可以存储过程的地址。
声明
要声明过程指针,使用 Sub 或 Function 关键字,后跟任何参数和返回值类型:
start GeSHi
' 声明一个指向无参数子过程的指针
Dim pointerToProcedure As Subend GeSHi
过程指针存储过程地址,使用 Operator @(取地址)或 ProcPtr 运算符 获取:
start GeSHi
'' pfunc.bi
Function Add (a As Integer, b As Integer) As Integer
Return a + b
End Function
Dim pFunc As Function (As Integer, As Integer) As Integer = @Addend GeSHi
调用过程指针
关于过程指针有趣的地方在于它们可以像过程一样被调用:
start GeSHi
'' .. 同前面的 Add 和 pFunc ..
#include once "pfunc.bi"
Print "3 + 4 = " & pFunc(3, 4)end GeSHi
子程序指针的调用示例,请参见 Operator @ (Address of) 页面。
注意:通过过程指针调用过程时,括号包围参数列表(即使为空)是必须的,以解决与简单访问指针值的歧义。
向过程传递过程指针
向其他过程传递过程指针同样类似:
start GeSHi
'' .. 同前面的 Add 和 pFunc ..
#include once "pfunc.bi"
Function DoOperation (a As Integer, b As Integer, operation As Function (As Integer, As Integer) As Integer) As Integer
Return operation(a, b)
End Function
Print "3 + 4 = " & DoOperation(3, 4, @Add)end GeSHi
由于过程指针声明可能很长,通常为过程指针创建类型别名会有所帮助,使代码更清晰:
start GeSHi
'' .. 同前面的 Add 和 pFunc ..
#include once "pfunc.bi"
Type operation As Function (As Integer, As Integer) As Integer
Function DoOperation (a As Integer, b As Integer, op As operation) As Integer
Return op(a, b)
End Function
Print "3 + 4 = " & DoOperation(3, 4, @Add)end GeSHi
指向过程指针的指针
由于过程指针的语法不允许声明指向过程指针的指针(当过程是函数时,因为 ptr 适用于返回类型而非过程),所以使用类型别名。注意,调用过程时,需要用括号将解引用的指向过程指针的指针括起来。这是因为函数调用运算符 () 的优先级高于 Operator *(取值):
start GeSHi
Function Halve (ByVal i As Integer) As Integer
Return i / 2
End Function
Function Triple (ByVal i As Integer) As Integer
Return i * 3
End Function
Type operation As Function (ByVal As Integer) As Integer
' 一个过程指针数组,NULL 表示
' 数组结尾
Dim operations(20) As operation = _
{ @Halve, @Triple, 0 }
Dim i As Integer = 280
' 通过指向过程指针的指针遍历数组,
' 对变量应用所有操作
Dim op As operation Ptr = @operations(0)
While (*op <> 0)
' 调用指针所指向的过程,注意额外的括号
i = (*op)(i)
op += 1
Wend
Print "Value of 'i' after all operations performed: " & iend GeSHi
指向成员过程的指针
在 fbc 1.10.0 之前,方法指针尚未实现,但可以通过使用静态包装器来解决:
start GeSHi
/''
' 本示例展示了在 fbc 1.10.0 之前,如何模拟获取类方法指针,
' 直到编译器正确实现该功能为止。
'
' 当此功能受支持(自 fbc 1.10.0 起)时,只需移除此处展示的静态包装器
' 函数,即可保持兼容性。
'/
Type T
Declare Function test(ByVal number As Integer) As Integer
Declare Static Function test(ByRef This As T, ByVal number As Integer) As Integer
Dim As Integer i = 420
End Type
Function T.test(ByVal number As Integer) As Integer
Return i + number
End Function
Function T.test(ByRef This As T, ByVal number As Integer) As Integer
Return This.test(number)
End Function
Dim p As Function(ByRef As T, ByVal As Integer) As Integer
p = @T.test
Dim As T obj
Print p(obj, 69) '' prints 489end GeSHi
自 fbc 1.10.0 起,方法指针通过更新 Procptr 运算符来实现:
start GeSHi
/''
' 本示例展示了自 fbc 1.10.0 起,如何直接获取类方法指针。
'/
Type T
Declare Function test(ByVal number As Integer) As Integer
Dim As Integer i = 420
End Type
Function T.test(ByVal number As Integer) As Integer
Return i + number
End Function
Dim p As Function(ByRef As T, ByVal As Integer) As Integer
p = ProcPtr(T.test) '' or 'p = @T.test'
Dim As T obj
Print p(obj, 69) '' prints 489end GeSHi
过程指针声明的类型规则
过程指针声明允许向指针赋值:
- 不仅是具有相同参数类型的过程,以及(如有)相同结果类型的过程,
- 还包括具有逆变参数(按引用或按指针)和/或协变结果(按引用或按指针)的过程。
向函数指针赋值具有逆变参数和协变结果(均按指针)的函数:
start GeSHi
'向函数指针赋值具有以下特征的函数的示例:
' - 逆变参数(按指针),
' - 以及协变结果(按指针)。
Type A
Dim As Integer I
Declare Constructor ()
Declare Destructor ()
End Type
Constructor A ()
Print " A instance constructed", @This
End Constructor
Destructor A ()
Print " A instance destroyed", @This
End Destructor
Type B Extends A
Dim As Integer J
Declare Constructor ()
Declare Constructor (ByRef a0 As A)
Declare Destructor ()
End Type
Constructor B ()
Print " B instance constructed", @This
End Constructor
Constructor B (ByRef a0 As A)
Cast(A, This) = a0
Print " B instance constructed", @This
End Constructor
Destructor B ()
Print " B instance destroyed", @This
End Destructor
Function f (ByVal pa0 As A Ptr) As B Ptr
Return New B(*pa0)
End Function
Scope
Dim As Function (ByVal As B Ptr) As A Ptr pf = @f
Print "'Scope : Dim As B b0':"
Dim As B b0
Print
Print "'Dim As A Ptr pab = pf(@b0)':"
Dim As A Ptr pab = pf(@b0)
Print
Print "'Delete CPtr(B Ptr, pab)':"
Delete CPtr(B Ptr, pab)
Print
Print "'End Scope':"
End Scope
Sleepend GeSHi
向函数指针赋值具有逆变参数和协变结果(均按引用)的函数:
start GeSHi
'向函数指针赋值具有以下特征的函数的示例:
' - 逆变参数(按引用),
' - 以及协变结果(按引用)。
Type A Extends Object
Dim As Integer I
Declare Constructor ()
Declare Virtual Destructor ()
End Type
Constructor A ()
Print " A instance constructed", @This
End Constructor
Destructor A ()
Print " A instance destroyed", @This
End Destructor
Type B Extends A
Dim As Integer J
Declare Constructor ()
Declare Constructor (ByRef a0 As A)
Declare Virtual Destructor ()
End Type
Constructor B ()
Print " B instance constructed", @This
End Constructor
Constructor B (ByRef a0 As A)
Cast(A, This) = a0
Print " B instance constructed", @This
End Constructor
Destructor B ()
Print " B instance destroyed", @This
End Destructor
Function f (ByRef a0 As A) ByRef As B
Return *New B(a0)
End Function
Scope
Dim As Function (ByRef As B) ByRef As A pf = @f
Print "'Scope : Dim As B b0':"
Dim As B b0
Print
Print "'Dim Byref As A rab = pf(b0)':"
Dim ByRef As A rab = pf(b0)
Print
Print "'Delete @rab':"
Delete @rab
Print
Print "'End Scope':"
End Scope
Sleepend GeSHi
参见
SubFunctionPointerOperator @ (Address of)ProcPtr operator
返回 目录