Указатели, которые указывают на процедуры
Так же, как указатели можно сделать для типов
Integer
или
Single, можно сделать их и для
процедур, то есть, они могут хранить адрес процедуры.
Декларация
Чтобы объявить указатель на процедуру, нужно использовать ключевые слова
Sub
или
Function, а затем уже любые
параметры и тип возвращаемого значения:
' объявляет указатель на процедуру, которая не принимает
аргументов
Dim pointerToProcedure As Sub
Указатель на процедуру хранит адрес процедуры, который извлекается с помощью
оператора @ (адрес из) или
Procptr
оператора:
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
Вызов процедуры указателя
Интересной особенностью процедуры указателя является то, что они могут
вызываться как обычная процедура:
'' .. Сложение с помощью pFunc ..
#include once "pfunc.bi"
Print "3 + 4 = " & pFunc(3, 4)
Передача указателей на процедуры в процедуру
Передача указателей на процедуры в другие процедуры также просто:
'' .. Сложение с помощью 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)
Поскольку декларации указателя процедуры могут быть длинными, можно создать
псевдоним типа для указателя процедуры, чтобы сделать более удобный код:
'' .. Сложение с помощью 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)
Указатели на процедурные указатели
Поскольку синтаксис указателя процедуры не позволяет сделать декларацию
указателя на указатель процедуры, то для этого псевдоним типа используется.
Обратите внимание, как надо окружать в скобках разыменованный указатель на
указатель процедуры. Это потому, что оператор вызова функции '()' имеет
более высокий приоритет, чем
оператор *
(значение из):
Sub Halve (ByRef i As Integer)
i /= 2
End Sub
Sub Triple (ByRef i As Integer)
i *= 3
End Sub
Type operation As Sub (ByRef As Integer)
' массив процедурных указателей, NULL указывает
' на конец массива
Dim operations(20) As operation = _
{ @Halve, @Triple, 0 }
Dim i As Integer = 280
' применить все
operations в переменную, путем использования итератора
' для массива с
указателями на указатели процедуры
Dim op As operation Ptr = @operations(0)
While (0 <> *op)
' вызываем процедуры по
порядку, обратите внимание на дополнительные скобки
(*op)(i)
op += 1
Wend
Print "Value of 'i' after all operations performed: " & i
Указатели на процедуры-элементы
Метод указателей еще не реализован, но это можно обойти, используя
статический враппер:
/'
' В этом примере показано, как можно имитировать получения указателя на метод
класса,
' до тех пор, пока поддержка не будет реализована должным образом в
компиляторе.
'
' Когда это будет поддерживаться, вам только нужно будет удалить
статический враппер
' функции, представленный здесь, чтобы сохранить совместимость.
'/
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) '' печатает 489
См. также