Skip to content

运算符重载


改变用户自定义类型与内置运算符的交互方式。

概述

全局运算符

成员运算符

运算符特殊情况:'.'(成员访问)、'@'(取地址)、'->'(指针成员访问)和 '*'(取值)

概述

简单来说,运算符就是过程,其参数称为操作数。接受一个操作数的运算符(如 Operator Not)称为一元运算符,接受两个操作数的运算符(如 Operator +)称为二元运算符,接受三个操作数的运算符(如 Operator Iif)称为三元运算符

大多数运算符不像过程那样被调用,而是将运算符符号放在操作数旁边。对于一元运算符,操作数放在符号右侧;对于二元运算符,操作数——称为左操作数和右操作数——分别放在运算符符号的左右两侧。FreeBASIC 有一个三元运算符 Operator Iif,它像过程一样被调用,操作数以逗号分隔并用括号括起来。

例如,以下代码调用 Operator Iif 来判断指针是否有效。如果有效,则调用 Operator * (Value of) 对指针解引用;否则调用 Operator / (Divide) 计算二十除以四的结果:

start GeSHi

vb
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) 则不同。在示例中,pOperator * (Value of) 的操作数,204 分别是 Operator / (Divide) 的左操作数和右操作数。

FreeBASIC 中的所有运算符都预定义为接受标准数据类型(如 IntegerSingle)的操作数,但也可以为用户自定义类型进行重载,即可以定义为接受对象作为操作数。可以重载的运算符有两类:全局运算符成员运算符

全局运算符

全局运算符是在模块级作用域(全局)中声明的运算符,包括:- (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)AbsSgnFixFracIntExpLogSinAsinCosAcosTanAtanLenSqr

声明自定义全局运算符与声明过程类似。使用 Declare 关键字配合 Operator 关键字,运算符符号后跟括号括起的逗号分隔参数列表,代表传入运算符的操作数。与过程不同,运算符默认可以重载,因此声明自定义运算符时不需要 Overload 关键字。运算符的至少一个参数必须是用户自定义类型(毕竟,接受内置类型参数的运算符已经定义好了)。

以下示例声明了接受用户自定义类型操作数的全局运算符 - (Negate)+ (Multiply)

start GeSHi

vb
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

end GeSHi

此处为类型 Rational 定义了全局运算符,并在 r3 的初始化表达式中使用。输出结果为 -6/12

成员运算符

成员运算符在 TypeClass 定义内部声明,类似于成员过程,包括转换和赋值运算符:Operator Cast (Cast)Operator @ (Address of)Operator [] (Pointer index)Operator New OverloadOperator Delete OverloadOperator 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)

声明成员运算符时,使用 DeclareOperator 关键字,后跟运算符符号及参数列表。与成员过程一样,成员运算符在 TypeClass 定义外部定义,符号名称前缀为所属 TypeClass 的名称。

以下示例为用户自定义类型的对象重载了成员运算符 Operator Cast (Cast)*= (Multiply and assign)

start GeSHi

vb
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

end 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) 用于通过指向变量的指针访问该变量。

在正常情况下,这些运算符的操作数必须是指针:

vb
Declare Operator -> ( ByRef lhs As T Ptr ) ByRef As U
Declare Operator * ( ByRef rhs As T Ptr ) ByRef As T

重载这些运算符可以创建一个指针包装类,使其行为像指针本身:

vb
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

vb
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

Sleep

end 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

vb
#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

Sleep

end 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

返回 目录

基于 FreeBASIC 官方文档翻译 如有侵权请联系我们删除
FreeBASIC 是开源项目,与微软公司无隶属关系