### Operator Overloading

Changing the way user defined types work with built-in operators.

Overview

Global Operators

Member Operators

__Overview__
Simply, operators are procedures, and their arguments are called

Most operators are not called like procedures. Instead, their operator symbol is placed next to their operands. For unary operators, their sole operand is placed to the right of the symbol. For binary operators, their operands - referred to as the left and right-hand side operands - are placed to the left and right of the operator symbol. FreeBASIC has one ternary operator,

*operands*. Operators that take one operand (`Operator Not`) are called*unary operators*, operators that take two operands (`Operator +`) are called*binary operators*and operators taking three operands (`Operator Iif`) are called*ternary operators*.Most operators are not called like procedures. Instead, their operator symbol is placed next to their operands. For unary operators, their sole operand is placed to the right of the symbol. For binary operators, their operands - referred to as the left and right-hand side operands - are placed to the left and right of the operator symbol. FreeBASIC has one ternary operator,

`Operator Iif`, and it is called like a procedure, with its operands comma-separated surrounded by parenthesis. For example, the following code calls`Operator Iif`to determine if a pointer is valid. If it is,`Operator * (Value of)`is called to dereference the pointer, and if not,`Operator / (Divide)`is called to find the value of twenty divided by four.Dim i As Integer = 420

Dim p As Integer Ptr = @i

Dim result As Integer = IIf( p, *p, CInt( 20 / 4 ) )

Dim p As Integer Ptr = @i

Dim result As Integer = IIf( p, *p, CInt( 20 / 4 ) )

Notice the call to

All operators in FreeBASIC are predefined to take operands of standard data types, like

`Operator Iif`is similar to a procedure call, while the calls to`Operator * (Value of)`and`Operator / (Divide)`are not. In the example,`is the operand to`*p*`Operator * (Value of)`, and`and`*20*`are the left and right-hand side operands of`*4*`Operator / (Divide)`, respectively.All operators in FreeBASIC are predefined to take operands of standard data types, like

`Integer`and`Single`, but they may also be overloaded for user-defined types; that is, they can be defined to accept operands that are objects as well. There are two types of operators that can be overloaded,*global operators*and*member operators*.

__Global Operators__
Global operators are those that are declared in module-level scope (globally). These are the operators

Declaring a custom global operator is similar to declaring a procedure. The

The following example declares the global operators

`- (Negate)`,`Not (Bitwise not)`,`-> (Pointer to member access)`,`* (Value of)`,`+ (Add)`,`- (Subtract)`,`* (Multiply)`,`/ (Divide)`,`\ (Integer divide)`,`& (Concatenate)`,`Mod (Modulus)`,`Shl (Shift left)`,`Shr (Shift right)`,`And (Bitwise and)`,`Or (Bitwise or)`,`Xor (Bitwise xor)`,`Imp (Bitwise imp)`,`Eqv (Bitwise eqv)`,`^ (Exponentiate)`,`= (Equal)`,`<> (Not equal)`,`< (Less than)`,`> (Greater than)`,`<= (Less than or equal)`and`>= (Greater than or equal)`.Declaring a custom global operator is similar to declaring a procedure. The

`Declare`keyword is used with the`Operator`keyword. The operator symbol is placed next followed by the comma-separated list of parameters surrounded in parenthesis that will represent the operands passed to the operator. Unlike procedures, operators can be overloaded by default, so the`Overload`keyword is not necessary when declaring custom operators. At least one of the operator's parameters must be of user-defined type (after all, operators with built-in type parameters are already defined).The following example declares the global operators

`- (Negate)`and`+ (Multiply)`to accept operands of a user-defined type.Type Rational

As Integer numerator, denominator

End Type

Operator - (ByRef rhs As Rational) As Rational

Return Type(-rhs.numerator, rhs.denominator)

End Operator

Operator * (ByRef lhs As Rational, ByRef rhs As Rational) As Rational

Return Type(lhs.numerator * rhs.numerator, _

lhs.denominator * rhs.denominator)

End Operator

Dim As Rational r1 = (2, 3), r2 = (3, 4)

Dim As Rational r3 = -(r1 * r2)

Print r3.numerator & "/" & r3.denominator

As Integer numerator, denominator

End Type

Operator - (ByRef rhs As Rational) As Rational

Return Type(-rhs.numerator, rhs.denominator)

End Operator

Operator * (ByRef lhs As Rational, ByRef rhs As Rational) As Rational

Return Type(lhs.numerator * rhs.numerator, _

lhs.denominator * rhs.denominator)

End Operator

Dim As Rational r1 = (2, 3), r2 = (3, 4)

Dim As Rational r3 = -(r1 * r2)

Print r3.numerator & "/" & r3.denominator

Here the global operators are defined for type

`, and are used in the initialization expression for`*Rational*`. The output is`*r3*`.`*-6/12*

__Member Operators__
Member operators are declared inside a

When declaring member operators, the

The following example overloads the member operators

`Type`or`Class`definition, like member procedures, and they are the cast and assignment operators`Let (Assign)`,`Operator Cast (Cast)`,`+= (Add and assign)`,`-= (Subtract and assign)`,`*= (Multiply and assign)`,`/= (Divide and assign)`,`\= (Integer divide and assign)`,`^= (Exponentiate and assign)`,`&= (Concat and assign)`,`Mod= (Modulus and assign)`,`Shl= (Shift left and assign)`,`Shr= (Shift right and assign)`,`And= (Conjunction and assign)`,`Or= (Inclusive disjunction and assign)`,`Xor= (Exclusive disjunction and assign)`,`Imp= (Implication and assign)`and`Eqv= (Equivalence and assign)`.When declaring member operators, the

`Declare`and`Operator`keywords are used followed by the operator symbol and its parameter list. Like member procedures, member operators are defined outside the`Type`or`Class`definition, and the symbol name is prefixed with the name of the`Type`or`Class`name.The following example overloads the member operators

`Operator Cast (Cast)`and`*= (Multiply and assign)`for objects of a user-defined type.Type Rational

As Integer numerator, denominator

Declare Operator Cast () As Double

Declare Operator Cast () As String

Declare Operator *= (ByRef rhs As Rational)

End Type

Operator Rational.Cast () As Double

Return numerator / denominator

End Operator

Operator Rational.Cast () As String

Return numerator & "/" & denominator

End Operator

Operator Rational.*= (ByRef rhs As Rational)

numerator *= rhs.numerator

denominator *= rhs.denominator

End Operator

Dim As Rational r1 = (2, 3), r2 = (3, 4)

r1 *= r2

Dim As Double d = r1

Print r1, d

As Integer numerator, denominator

Declare Operator Cast () As Double

Declare Operator Cast () As String

Declare Operator *= (ByRef rhs As Rational)

End Type

Operator Rational.Cast () As Double

Return numerator / denominator

End Operator

Operator Rational.Cast () As String

Return numerator & "/" & denominator

End Operator

Operator Rational.*= (ByRef rhs As Rational)

numerator *= rhs.numerator

denominator *= rhs.denominator

End Operator

Dim As Rational r1 = (2, 3), r2 = (3, 4)

r1 *= r2

Dim As Double d = r1

Print r1, d

Notice that the member operator `Print`statement,

`Cast (Cast)`is declared twice, once for the conversion to`Double`and once for the conversion to`String`. This is the only operator (or procedure) that can be declared multiple times when only the return type differs. The compiler decides which cast overload to call based on how the object is used (in the initialization of the`Double``,`*d*`is called, and in the`*Rational.Cast as double*`is used instead).`*Rational.Cast as string*Back to Programmer's Guide