Skip to content

过程指针


指向过程的指针

就像指针可以指向 IntegerSingle 类型一样,指针也可以指向过程,即它们可以存储过程的地址。

声明

要声明过程指针,使用 SubFunction 关键字,后跟任何参数和返回值类型:

start GeSHi

vb
' 声明一个指向无参数子过程的指针
Dim pointerToProcedure As Sub

end GeSHi

过程指针存储过程地址,使用 Operator @(取地址)或 ProcPtr 运算符 获取:

start GeSHi

vb
'' 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 = @Add

end GeSHi

调用过程指针

关于过程指针有趣的地方在于它们可以像过程一样被调用:

start GeSHi

vb
'' .. 同前面的 Add 和 pFunc ..
#include once "pfunc.bi"

Print "3 + 4 = " & pFunc(3, 4)

end GeSHi

子程序指针的调用示例,请参见 Operator @ (Address of) 页面。

注意:通过过程指针调用过程时,括号包围参数列表(即使为空)是必须的,以解决与简单访问指针值的歧义。

向过程传递过程指针

向其他过程传递过程指针同样类似:

start GeSHi

vb
'' .. 同前面的 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

vb
'' .. 同前面的 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

vb
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: " & i

end GeSHi

指向成员过程的指针

在 fbc 1.10.0 之前,方法指针尚未实现,但可以通过使用静态包装器来解决:

start GeSHi

vb
/''
 ' 本示例展示了在 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 489

end GeSHi

自 fbc 1.10.0 起,方法指针通过更新 Procptr 运算符来实现:

start GeSHi

vb
/''
 ' 本示例展示了自 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 489

end GeSHi

过程指针声明的类型规则

过程指针声明允许向指针赋值:

  • 不仅是具有相同参数类型的过程,以及(如有)相同结果类型的过程,
  • 还包括具有逆变参数(按引用或按指针)和/或协变结果(按引用或按指针)的过程。

向函数指针赋值具有逆变参数和协变结果(均按指针)的函数:

start GeSHi

vb
'向函数指针赋值具有以下特征的函数的示例:
'   - 逆变参数(按指针),
'   - 以及协变结果(按指针)。

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

Sleep

end GeSHi

向函数指针赋值具有逆变参数和协变结果(均按引用)的函数:

start GeSHi

vb
'向函数指针赋值具有以下特征的函数的示例:
'   - 逆变参数(按引用),
'   - 以及协变结果(按引用)。

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

Sleep

end GeSHi

参见

  • Sub
  • Function
  • Pointer
  • Operator @ (Address of)
  • ProcPtr operator

返回 目录

基于 FreeBASIC 官方文档翻译 如有侵权请联系我们删除
FreeBASIC 是开源项目,与微软公司无隶属关系