Byval и Byref

Сказать по чести, способы передачи параметров процедурам или функциям, наверно нужно было осветить в теме про функции. Но мне хотелось, чтобы вы сначала поняли что такое указатели.

Способы передачи параметров в функции или процедуры:

  1. Byval  - передается само значение
  2. Byref - передается указатель на это значение.

Когда мы пишем например так:

Sub qq( a As Integer)

На самом деле это сокращенный тип записи:

Sub qq(Byval a As Integer)

При таких записях, точнее так передавая параметр, в нашей функции попросту создается новая переменная и ей присваивается значение , которое передается при вызове функции.

Два примера(по сути одинаковые программы):

Сокращенная запись без Byval:

Sub qq(a As Integer)
    a+=1
    ? a
End Sub
Dim a As Integer=5
qq(a)
? a
Sleep

Запись с Byval:

Sub qq(Byval a As Integer)
    a+=1
    ? a
End Sub
Dim a As Integer=5
qq(a)
? a
Sleep


Примечание: Для строк используется обратное правило. То есть по умолчанию без указания способа передачи параметров, строки передаются по Byref.

А теперь перейдем к другому способу передачи параметра Byref.
Когда мы используем при передаче параметра ключевое слово Byref, мы передаем процедуре не значение, а реальный адрес этой переменной. И все что мы изменим с этой переменной в процедуре изменится и для основного кода. Пример:

Sub qq(Byref a As Integer)
    a+=1
    ? a
End Sub
Dim a As Integer=5
qq(a)
? a
Sleep


Заметили, что результат отличается от результата примеров с Byval ?  Все правильно: Byval работает с копией значения переменной, а Byref с настоящим значением переменной.

Если не использовать ключевое слово Byref , то нам придется писать примерно такое:

Sub qq(a As Integer Ptr)
    *a+=1
    ? *a
End Sub
Dim a As Integer=5
qq(@a)
? a
Sleep


Согласитесь, что для выполнения этой задачи, удобнее использовать ключевое слово Byref . 

И в дополнение к статье про функции:

В процедуры или функции параметры можно передавать по умолчанию. Здесь вы должны вспомнить статьи про структуры. Принцип схожий.

Пример:

Sub qq(a As Integer=10, b As Integer, c As Integer=15)
    a+=1
    ? a
End Sub
qq(1,2,3)
qq(,5)
Sleep


Вы наверно заметили, что я к двум из трех параметров приписал значения 10 и 15. Это значения по умолчанию и параметры a и с уже указывать не обязательно. Если укажите значения в параметрах при вызове, тогда процедура возмет значения, указанные вами. А если не укажете, то возмет значения по умолчанию. Смотрите на вызов процедуры. Первый раз вызывая процедуру, мы передали ей все параметры и в результате переменная a в процедуре при сложении 1+1 стала равна 2. При втором вызове, мы указали только обязательный параметр b и значение переменной a стало равно 10+1=11.
Обратите внимание на синтаксис вызова с параметрами по умолчанию. Если опускаемые параметры по умолчанию идут впереди , то вместо них просто ставится запятая. Если же позади, то вообще ничего писать не нужно.
Поизучайте этот пример, вызывая разными способами.
Мне хотелось бы добавить то, что я упустил в прошлой статье про функции. В той статье я заикнулся о том, что можно возвращать значения из функции тремя разными способами, но забыл рассказать чем они отличаются.

  1. Return значение  (возвращает значение сразу  выходя их функции)
  2. Function= значение (присваивает результат функции, но не выходит из функции до тех пор, пока не достигнут ее конец или не встретился оператор Return)
  3. Имя функции = значение (тоже что и второй пункт)

До сих пор мы создавали свои функции, процедуры и ниже в нашем коде их вызывали. Все правильно, такой способ приносит схематичное построение вашей программы: вверху функции , внизу код. С другой стороны не все хотят следовать таким правилам, да и кроме того если вы будете использовать написанные кем нибудь функции в специальных файлах-библиотеках, то просто так вызвать функцию не получится.  Ее нужно будет сначала продекларировать. Декларация-это примерно тоже, что объявление переменных. Декларации делаются чаще всего в начале кода. Для декларации функции, процедуры, конструкторов, деструкторов применяют команду Declare и выглядит это таким образом:

Declare Sub qq(a As Integer=10, b As Integer, c As Integer=15)
qq(1,2,3)
qq(,5)
Sleep
 End
Sub qq(a As Integer=10, b As Integer, c As Integer=15)
    a+=1
    ? a
End Sub


Обратите внимание. При декларации берется первая строчка процедуры и впереди  добавляется команда Declare. Так мы даем компилятору знать , что существует такая процедура и мы будем ее использовать из нашего основного кода, либо из других модульных файлов. Теперь мы можем вверху писать код и вызывать функции или процедуры находящиеся внизу. Попробуйте это проделать без декларации.
В следующей статье мы наконец научимся использовать функции и процедуры,  написанные другими людьми. Всего доброго!

содержание | назад | вперед