运算符重载
- Source: https://www.freebasic.net/wiki/wikka.php?wakka=ProPgOperatorOverloading
- Last revised: 2024-03-24
改变用户自定义类型与内置运算符的交互方式。
运算符特殊情况:'.'(成员访问)、'@'(取地址)、'->'(指针成员访问)和 '*'(取值)
概述
简单来说,运算符就是过程,其参数称为操作数。接受一个操作数的运算符(如 Operator Not)称为一元运算符,接受两个操作数的运算符(如 Operator +)称为二元运算符,接受三个操作数的运算符(如 Operator Iif)称为三元运算符。
大多数运算符不像过程那样被调用,而是将运算符符号放在操作数旁边。对于一元运算符,操作数放在符号右侧;对于二元运算符,操作数——称为左操作数和右操作数——分别放在运算符符号的左右两侧。FreeBASIC 有一个三元运算符 Operator Iif,它像过程一样被调用,操作数以逗号分隔并用括号括起来。
例如,以下代码调用 Operator Iif 来判断指针是否有效。如果有效,则调用 Operator * (Value of) 对指针解引用;否则调用 Operator / (Divide) 计算二十除以四的结果:
start GeSHi
Dim i As Integer = 420
Dim p As Integer Ptr = @i
Dim result As Integer = IIf( p, *p, CInt( 20 / 4 ) )end GeSHi
注意,调用 Operator Iif 类似于过程调用,而调用 Operator * (Value of) 和 Operator / (Divide) 则不同。在示例中,p 是 Operator * (Value of) 的操作数,20 和 4 分别是 Operator / (Divide) 的左操作数和右操作数。
FreeBASIC 中的所有运算符都预定义为接受标准数据类型(如 Integer 和 Single)的操作数,但也可以为用户自定义类型进行重载,即可以定义为接受对象作为操作数。可以重载的运算符有两类:全局运算符 和 成员运算符。
全局运算符
全局运算符是在模块级作用域(全局)中声明的运算符,包括:- (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)、>= (Greater than or equal)、Abs、Sgn、Fix、Frac、Int、Exp、Log、Sin、Asin、Cos、Acos、Tan、Atan、Len 和 Sqr。
声明自定义全局运算符与声明过程类似。使用 Declare 关键字配合 Operator 关键字,运算符符号后跟括号括起的逗号分隔参数列表,代表传入运算符的操作数。与过程不同,运算符默认可以重载,因此声明自定义运算符时不需要 Overload 关键字。运算符的至少一个参数必须是用户自定义类型(毕竟,接受内置类型参数的运算符已经定义好了)。
以下示例声明了接受用户自定义类型操作数的全局运算符 - (Negate) 和 + (Multiply):
start GeSHi
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.denominatorend GeSHi
此处为类型 Rational 定义了全局运算符,并在 r3 的初始化表达式中使用。输出结果为 -6/12。
成员运算符
成员运算符在 Type 或 Class 定义内部声明,类似于成员过程,包括转换和赋值运算符:Operator Cast (Cast)、Operator @ (Address of)、Operator [] (Pointer index)、Operator New Overload、Operator Delete Overload、Operator For (iteration)、Operator Step (Iteration)、Operator Next (Iteration)、Let (Assign)、+= (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) 和 Eqv= (Equivalence and assign)。
声明成员运算符时,使用 Declare 和 Operator 关键字,后跟运算符符号及参数列表。与成员过程一样,成员运算符在 Type 或 Class 定义外部定义,符号名称前缀为所属 Type 或 Class 的名称。
以下示例为用户自定义类型的对象重载了成员运算符 Operator Cast (Cast) 和 *= (Multiply and assign):
start GeSHi
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, dend GeSHi
注意,成员运算符 Cast (Cast) 被声明了两次,一次用于转换为 Double,一次用于转换为 String。这是唯一可以仅凭返回类型不同而多次声明的运算符(或过程)。编译器根据对象的使用方式决定调用哪个 cast 重载(在 Double 类型变量 d 的初始化中调用 Rational.Cast as double,而在 Print 语句中则使用 Rational.Cast as string)。
运算符特殊情况:'.'(成员访问)、'@'(取地址)、'->'(指针成员访问)和 '*'(取值)
- 重载
Operator . (Member access)
operator '.' (member access) 不能被重载。
- 重载
Operator @ (Address of)
operator @ (Address of) 用于访问变量的地址。
重载此运算符对对象来说意义不大,而且一旦重载,就无法再获取其地址了。
- 重载
Operator -> (Pointer to member access)和Operator * (Value of)
operator -> (Pointer to member access) 用于通过指向对象实例的指针访问该实例的任意成员。
operator * (Value of) 用于通过指向变量的指针访问该变量。
在正常情况下,这些运算符的操作数必须是指针:
Declare Operator -> ( ByRef lhs As T Ptr ) ByRef As U
Declare Operator * ( ByRef rhs As T Ptr ) ByRef As T重载这些运算符可以创建一个指针包装类,使其行为像指针本身:
Declare Operator -> ( ByRef lhs As wrapperClass ) ByRef As U
Declare Operator * ( ByRef rhs As wrapperClass ) ByRef As U这样,包装类就可以像下面这样使用(访问成员):
wrapper->member
而不必写成:
wrapper.realPointer->member
以及:
(*wrapper).member
而不必写成:
(*wrapper.realPointer).member
关于重载 operator -> (pointer to member access) 的特殊情况说明:
operator -> (pointer to member access) 在重载方面与其他运算符有所不同:
它不只是返回重载过程头中指定的用户数据类型,
而是隐式地在返回该用户数据类型之后再应用
operator . (member access)。
operator -> (pointer to member access) 通常与 operator * (Value of) 配合使用,用于实现"智能指针"。
- 使用智能指针
智能指针的使用可以对由 New 创建的动态引用进行自动管理(每个引用在其智能指针超出作用域时自动销毁),而无需复制这些引用。
智能指针是什么的提示:
智能指针是一种行为像指针但能做更多事情的对象。
该对象像指针一样灵活,同时又具有对象的优势(如构造函数和析构函数自动调用)。
因此,当该对象超出作用域时,智能指针的析构函数会自动调用,并删除用户指针。
由于智能指针必须像指针一样工作,所以它必须支持与指针相同的接口。
因此,它必须支持以下操作:
解引用(
operator * (Value of))间接访问(
operator -> (pointer to member access))
operator * (Value of) 和 operator -> (pointer to member access) 必须通过引用返回(在声明返回类型时使用 Byref As .....)。
带接口的智能指针(指向 UDT)示例,包含:
公有默认构造函数
公有拷贝构造函数
公有析构函数
私有 UDT 指针及公有
operator cast (Cast)以只读方式访问私有 operator
let禁止赋值(此处未实现,以避免仅复制指针值)operator * (Value of)和operator -> (pointer to member access)
start GeSHi
Type UDT
Declare Constructor ()
Declare Destructor ()
Dim As String s = "object #0"
End Type
Constructor UDT ()
Print " UDT construction "; @This
End Constructor
Destructor UDT ()
Print " UDT destruction "; @This
End Destructor
Type SmartPointer
Public:
Declare Constructor () '' 从 _UDTname_ 指针构造智能指针(及 UDT 对象),
Declare Constructor (ByRef rhs As SmartPointer) '' 拷贝构造智能指针
Declare Operator Cast () As UDT Ptr '' 将私有 UDT 指针转换为 UDT 指针(只读)
Declare Destructor () '' 销毁智能指针(及 UDT 对象)
Private:
Dim As UDT Ptr p '' 私有 UDT 指针
Declare Operator Let (ByRef rhs As SmartPointer) '' 禁止赋值(避免复制实际指针)
End Type
Constructor SmartPointer ()
Print "SmartPointer construction "; @This
This.p = New UDT
End Constructor
Constructor SmartPointer (ByRef rhs As SmartPointer)
Print "SmartPointer copy-construction "; @This; " from "; @rhs
This.p = New UDT
*This.p = *rhs.p
End Constructor
Operator SmartPointer.Cast () As UDT Ptr
Return This.p
End Operator
Destructor SmartPointer ()
Print "SmartPointer destruction "; @This
Delete This.p
End Destructor
Operator * (ByRef sp As SmartPointer) ByRef As UDT '' 重载运算符 '*'
Print "SmartPointer operator '*'"
Return *Cast(UDT Ptr, sp) '' (returning byref)
End Operator '' to behave as pointer
Operator -> (ByRef sp As SmartPointer) ByRef As UDT '' 重载运算符 '->'
Print "SmartPointer operator '->'"
Return *Cast(UDT Ptr, sp) '' (returning byref)
End Operator '' to behave as pointer
Scope
Dim sp1 As SmartPointer
Print "'" & sp1->s & "'"
sp1->s = "object #1"
Print "'" & sp1->s & "'"
Print
Dim sp2 As SmartPointer = sp1
Print "'" & (*sp2).s & "'"
(*sp2).s = "object #2"
Print "'" & (*sp2).s & "'"
Print
Dim sp3 As SmartPointer = sp1
Print "'" & sp3->s & "'"
*sp3 = *sp2
Print "'" & sp3->s & "'"
sp3->s = "object #3"
Print "'" & sp3->s & "'"
Print
End Scope
Sleepend GeSHi
输出示例:
SmartPointer construction 1703576
UDT construction 10693312
SmartPointer operator '->'
'object #0'
SmartPointer operator '->'
SmartPointer operator '->'
'object #1'
SmartPointer copy-construction 1703524 from 1703576
UDT construction 10693384
SmartPointer operator '*'
'object #1'
SmartPointer operator '*'
SmartPointer operator '*'
'object #2'
SmartPointer copy-construction 1703472 from 1703576
UDT construction 10693456
SmartPointer operator '->'
'object #1'
SmartPointer operator '*'
SmartPointer operator '*'
SmartPointer operator '->'
'object #2'
SmartPointer operator '->'
SmartPointer operator '->'
'object #3'
SmartPointer destruction 1703472
UDT destruction 10693456
SmartPointer destruction 1703524
UDT destruction 10693384
SmartPointer destruction 1703576
UDT destruction 10693312适用于任意 UDT(或任意预定义类型)的扩展智能指针类型宏示例,具有扩展接口:
公有构造函数
只读公有引用计数器
公有析构函数
私有 UDT 指针及 2 个公有
cast运算符,以只读方式访问(数值和字符串形式)私有默认构造函数,禁止自我构造
私有拷贝构造函数,禁止克隆
私有 operator
let,禁止赋值operator * (Value of)和operator -> (pointer to member access)
start GeSHi
#Macro Define_SmartPointer (_UDTname_)
Type SmartPointer_##_UDTname_
Public:
Declare Constructor (ByVal rhs As _UDTname_ Ptr) '' 从 _UDTname_ 指针构造智能指针,
' '' 并递增引用计数器
Declare Static Function returnCount () As Integer '' 返回引用计数器值
Declare Operator Cast () As _UDTname_ Ptr '' 将私有 _UDTname_ 指针转换
' '' 为 _UDTname_ 指针(只读)
Declare Operator Cast () As String '' 将私有 _UDTname_ 指针转换
' '' 为字符串(只读)
Declare Destructor () '' 销毁智能指针
' '' 及 _UDTname_ 对象,
' '' 并递减引用计数器
Private:
Dim As _UDTname_ Ptr p '' 私有 _UDTname_ 指针
Static As Integer Count '' 私有引用计数器
Declare Constructor () '' 禁止默认构造
Declare Constructor (ByRef rhs As SmartPointer_##_UDTname_) '' 禁止拷贝构造
Declare Operator Let (ByRef rhs As SmartPointer_##_UDTname_) '' 禁止拷贝赋值
End Type
Dim As Integer SmartPointer_##_UDTname_.Count = 0
Constructor SmartPointer_##_UDTname_ (ByVal rhs As _UDTname_ Ptr)
If rhs <> 0 Then
This.p = rhs
SmartPointer_##_UDTname_.count += 1
End If
End Constructor
Static Function SmartPointer_##_UDTname_.returnCount () As Integer
Return SmartPointer_##_UDTname_.count
End Function
Operator SmartPointer_##_UDTname_.Cast () As _UDTname_ Ptr
Return This.p
End Operator
Operator SmartPointer_##_UDTname_.Cast () As String
Return Str(This.p)
End Operator
Destructor SmartPointer_##_UDTname_ ()
If This.p <> 0 Then
Delete This.p
SmartPointer_##_UDTname_.count -= 1
This.p = 0
End If
End Destructor
Operator * (ByRef sp As SmartPointer_##_UDTname_) ByRef As _UDTname_ '' 运算符 '*'(按引用返回)
' '' 以指针方式行为
Return ByVal sp '' 'Return *sp' 会导致无限循环
End Operator
Operator -> (ByRef sp As SmartPointer_##_UDTname_) ByRef As _UDTname_ '' 运算符 '->'(按引用返回)
' '' 以指针方式行为
Return ByVal sp
End Operator
#Endmacro
'--------------------------------------------------------------------------------------------------------
' 使用继承的全部八个关键字的示例:
' 'Extends'、'Base.'、'Base()'、'Object'、'Is' 运算符、'Virtual'、'Abstract'、'Override'
Type root Extends Object ' 'Extends' to activate RTTI by inheritance of predefined Object type
Public:
Declare Function ObjectHierarchy () As String
Declare Function ObjectName () As String
Declare Abstract Function ObjectRealType () As String '' 'Abstract' 声明无本地函数体,
' '' 必须被重写
Declare Virtual Destructor () '' 'Virtual' 声明析构函数
Protected:
Declare Constructor () '' 禁止从类型外部进行默认构造
Declare Constructor (ByRef _name As String = "") '' 禁止从类型外部进行构造
Declare Constructor (ByRef rhs As root) '' 禁止从类型外部进行拷贝构造
Declare Operator Let (ByRef rhs As root) '' 禁止从类型外部进行拷贝赋值
Private:
Dim Name As String
End Type '' 派生类型的成员数据可为空
Constructor root () '' 仅为避免编译错误(因继承要求)
End Constructor
Constructor root (ByRef _name As String = "") '' 仅为避免编译错误(因继承要求)
This.Name = _name
Print "root constructor:", This.Name
End Constructor
Function root.ObjectHierarchy () As String
Return "Object(forRTTI) <- root"
End Function
Function root.ObjectName () As String
Return This.Name
End Function
Virtual Destructor root ()
Print "root destructor:", This.Name
End Destructor
Operator root.Let (ByRef rhs As root) '' 仅为避免编译错误(因继承要求)
End Operator
Type animal Extends root '' 'Extends' 用于继承自 root
Declare Constructor (ByRef _name As String = "")
Declare Function ObjectHierarchy () As String
Declare Virtual Function ObjectRealType () As String Override '' 'Virtual' 声明带本地函数体的函数,
' '' 可以被重写
' '' 'Override' 用于检查该函数
' '' 是否真正重写了父类函数
Declare virtual Destructor () Override '' 'Virtual' 声明带本地函数体的析构函数
' '' 'Override' 用于检查该析构函数是否真正重写了父类析构函数
End Type
Constructor animal (ByRef _name As String = "")
Base(_name) '' 'Base()' 用于调用父类构造函数
Print " animal constructor:", This.ObjectName()
End Constructor
Function animal.ObjectHierarchy () As String
Return Base.ObjectHierarchy & " <- animal" '' 'Base.' 用于访问父类成员函数
End Function
Virtual Function animal.ObjectRealType () As String
Return "animal"
End Function
Virtual Destructor animal ()
Print " animal destructor:", This.ObjectName()
End Destructor
Type dog Extends animal '' 'Extends' 用于继承自 animal
Declare Constructor (ByRef _name As String = "")
Declare Function ObjectHierarchy () As String
Declare Function ObjectRealType () As String Override '' 'Override' 用于检查该函数是否真正
' '' override
Declare Destructor () Override '' 'Override' 用于检查该析构函数是否真正重写了父类析构函数
End Type '' 派生类型的成员数据可为空
Constructor dog (ByRef _name As String = "")
Base(_name) '' 'Base()' 用于调用父类构造函数
Print " dog constructor:", This.ObjectName()
End Constructor
Function dog.ObjectHierarchy () As String
Return Base.ObjectHierarchy & " <- dog" '' 'Base.' 用于访问父类成员函数
End Function
Function dog.ObjectRealType () As String
Return "dog"
End Function
Destructor dog ()
Print " dog destructor:", This.ObjectName()
End Destructor
Type cat Extends animal '' 'Extends' 用于继承自 animal
Declare Constructor (ByRef _name As String = "")
Declare Function ObjectHierarchy () As String
Declare Function ObjectRealType () As String Override '' 'Override' 用于检查该函数是否真正
' '' override
Declare Destructor () Override '' 'Override' 用于检查该析构函数是否真正重写了父类析构函数
End Type '' 派生类型的成员数据可为空
Constructor cat (ByRef _name As String = "")
Base(_name) '' 'Base()' 用于调用父类构造函数
Print " cat constructor:", This.ObjectName()
End Constructor
Function cat.ObjectHierarchy () As String
Return Base.ObjectHierarchy & " <- cat" '' 'Base.' 用于访问父类成员函数
End Function
Function cat.ObjectRealType () As String
Return "cat"
End Function
Destructor cat ()
Print " cat destructor:", This.ObjectName()
End Destructor
Sub PrintInfo (ByVal p As root Ptr) '' 参数为 'root Ptr' 或兼容类型(智能指针)
Print " " & p->ObjectName, " " & p->ObjectRealType, " ";
If *p Is dog Then '' 'Is' 用于检查与类型符号的兼容性
Print Cast(dog Ptr, p)->ObjectHierarchy
ElseIf *p Is cat Then '' 'Is' 用于检查与类型符号的兼容性
Print Cast(cat Ptr, p)->ObjectHierarchy
ElseIf *p Is animal Then '' 'Is' 用于检查与类型符号的兼容性
Print Cast(animal Ptr, p)->ObjectHierarchy
End If
End Sub
Define_SmartPointer(root) '' 智能指针定义
Scope
Print "reference counter value:"; SmartPointer_root.returnCount()
Print
Dim As SmartPointer_root sp(2) = {New animal("Mouse"), New dog("Buddy"), New cat("Tiger")}
Print
Print "reference counter value:"; SmartPointer_root.returnCount()
For I As Integer = 0 To 2
Print " " & sp(I), sp(I)->ObjectName()
Next I
Print
Print "Name:", "Object (real): Hierarchy:"
For I As Integer = 0 To 2
#if __FB_VERSION__ = "1.10.0" Or __FB_VERSION__ = "1.10.1"
PrintInfo(Cast(root Ptr, sp(I))) '' 错误规避
#else
PrintInfo(sp(I))
#endif
Next I
Print
End Scope
Print
Print "reference counter value:"; SmartPointer_root.returnCount()
Print
Sleepend GeSHi
输出示例:
reference counter value: 0
root constructor: Mouse
animal constructor: Mouse
root constructor: Buddy
animal constructor: Buddy
dog constructor: Buddy
root constructor: Tiger
animal constructor: Tiger
cat constructor: Tiger
reference counter value: 3
11145960 Mouse
11151496 Buddy
11151616 Tiger
Name: Object (real): Hierarchy:
Mouse animal Object(forRTTI) <- root <- animal
Buddy dog Object(forRTTI) <- root <- animal <- dog
Tiger cat Object(forRTTI) <- root <- animal <- cat
cat destructor: Tiger
animal destructor: Tiger
root destructor: Tiger
dog destructor: Buddy
animal destructor: Buddy
root destructor: Buddy
animal destructor: Mouse
root destructor: Mouse
reference counter value: 0返回 目录