Перегрузка операторов

Опция - перегрузка операторов предоставляет возможность назначать другие действия для стандартных операторов языка. Так например оператору + определить возможность возведения в степень или извлечение корня из числа. Конечно такая возможность будет работать только с тем типом данных для которых предназначена перегрузка, в остальных случаях это будет все тот же стандартный оператор . В языке С++ перегрузка операторов может выполняться не на все операторы. Однако сколько я не искал, в FreeBasic нигде не написано об таких вещах, возможно что ограничений нет.
По своей сути перегрузку операторов лучше использовать только тогда, когда это действительно облегчает читаемость программы, в остальных случаях это будет несерьезно. Например, глупо использовать оператор + как в примере ниже:

Type AA
  As Integer x
End Type

Operator + (l As AA) As String
    Return Str(l.x*l.x)
End Operator

Dim a As AA = Type(3)
Dim b As AA = Type(5)
Print  +a
Print  +b
Sleep

Данный код не может облегчать читаемость, более того он наверняка только запутает программиста, однако как возможный пример подойдет.

Я прошу прощения, что забыл в теме про структуры сообщить о возможности присваивать значения ее полям таким образом, как в примере выше. Запись:

Dim a As AA = Type(3)

полностью эквивалентна записи:

Dim a As AA
a.x=3


Первое что нужно знать при перегрузке операторов:  разные операторы работают с разным кол-вом аргументов. Так например оператор минус и плюс могут работать как с одним аргументом так и с двумя, а оператор равно только с двумя. Отсюда важно понимать, сколько передавать параметров при перегрузке.
Второе, что так же важно: перегрузка операторов не возможна без объявления своего собственного типа. К этому типу будут привязаны объекты, использующие перегруженные операторы. В нашем примере этим типом был тип AA. Все объекты, созданные на базе этого типа, могут использовать перегруженные операторы, для остальных типов данных это будет обычный оператор.
И наконец третье: операторы при перегрузке разделяются как бы на два типа. Для одних не нужно делать декларацию, поскольку они являются глобальными. Для другого типа операторов использование похоже на использование методов класса. 

Глобальные ( не нужно проводить декларацию):

  • - (отрицание)
  • Not (битовый отрицание)
  • -> (указатель на область памяти)
  • * (получение значения по адресу)
  • + (сложение)
  • - (вычитание)
  • * (умножение)
  • / (деление)
  • \ (деление без остатка)
  • & (объединение)
  • Mod (модуль числа)
  • Shl (битовый сдвиг влево)
  • Shr (битовый сдвиг вправо)
  • And (битовый И)
  • Or (битовый ИЛИ)
  • Xor (битовый исключающий ИЛИ)
  • Imp (битовый импликация)
  • Eqv (битовый эквивалент)
  • ^ (степень числа)
  • = (равно)
  • <> (не равно)
  • < (меньше)
  • > (больше)
  • <= (меньше или равно)
  • >= (больше или равно)


Неглобальные (необходима декларация):

  • Let (присвоение)
  • Cast (преобразование)
  • += (сложение и присвоение)
  • -= (вычитание и присвоение)
  • *= (умножение и присвоение)
  • /= (деление и присвоение)
  • \= (деление без остатка и присвоение)
  • ^= (возведение в степень и присвоение)
  • &= (объединение и присвоение)
  • Mod= (модуль числа и присвоение)
  • Shl= (сдвиг влево и присвоение)
  • Shr= (сдвиг вправо и присвоение)
  • And= (битовое И и присвоение)
  • Or= (битовое ИЛИ и присвоение)
  • Xor= (битовое исключающее ИЛИ и присвоение)
  • Imp= (импликация и присвоение)
  • Eqv= (эквивалент и присвоение)

Давайте вернемся к вышенаписанному примеру. Мы объявили свой тип данных AA. Далее на базе этого типа создали перегрузку оператора + . В данном случае этот оператор не декларируется, но параметр, который передается блоку должен иметь наш определяемый тип AA.  Возвращаемое значение в примере строковое, но оно может быть любое по вашему усмотрению. В самом блоке можно проводить любые вычисления и преобразования. Ниже мы создали два объекта с типом AA , а далее использовали перегруженный оператор для этих объектов. Теперь тот же пример, только с двумя аргументами:

Type AA
  As Integer x
End Type

Operator + (l As AA , r As AA) As String
    Return Str(l.x*r.x)
End Operator

Dim a As AA = Type(3)
Dim b As AA = Type(5)
Print  a+b
Sleep

Как видите оператор + может работать как с одним аргументом, так и с двумя. Можете заменить оператор + на оператор = разницы не будет. Но у вас не получится проделать это в первом примере, поскольку оператор равно должен иметь 2 аргумента.
Теперь я предлагаю пример с использованием декларации неглобальных операторов:

Type AA
     As Integer x
     Declare Operator ^= (l As AA)
End Type
 
Operator AA.^= (l As AA)
     x = l.x^3
End Operator

Dim As AA a = (2), b = (3)
 a ^= b
 b ^= a
Print a.x
Print b.x
Sleep


Данный пример является перегрузкой оператора ^= . Его назначение в этом примере возведение в степень тройки. Какие бы значения мы не присваивали полям объектов, они при использовании этого оператора, будут  возводится в степень тройки. В примере нет ничего сложного. Перегруженный оператор декларируется и объявляется как метод класса. В остальном все так же как с глобальными операторами.
Я понимаю, что данные примеры не показывают полезности перегрузки операторов. На самом деле я не считаю данную фичу чем-то полезным. На мой взгляд это лишнее извращение в коде. Однако это только мое субъективное мнение, возможно вы найдете применение этой возможности в ваших программах.

Всего доброго!

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