ZetCode

FreeBasic 析构函数关键字

最后修改日期:2025 年 6 月 16 日

FreeBasic 的 Destructor 关键字定义了一个特殊的成员函数,该函数在对象被销毁时自动调用。析构函数对于用户定义类型的正确资源清理至关重要。

基本定义

在 FreeBasic 中,Destructor 是 UDT(用户定义类型)的一个特殊方法,当对象超出范围或被显式删除时执行。它的名称与类型名称相同,前面加上波浪号(~)。

析构函数不能接受参数或返回值。它们的主要目的是释放对象在其生命周期内可能获取的资源,如内存、文件句柄或网络连接。

简单的析构函数示例

此示例展示了一个带有构造函数和析构函数的基本 UDT。

simple_destructor.bas
Type Resource
    Public:
        Declare Constructor()
        Declare Destructor()
    Private:
        id As Integer
End Type

Constructor Resource()
    Print "Resource acquired"
    id = 42
End Constructor

Destructor Resource()
    Print "Resource released for id "; id
End Destructor

Scope
    Dim res As Resource
End Scope

Print "After scope"

在这里,我们定义了一个带有构造函数和析构函数的 Resource 类型。当对象创建时,构造函数运行。当它超出范围时,析构函数会自动执行。这确保了正确的清理。

带有动态内存的析构函数

析构函数在管理动态分配的内存方面特别有用。

dynamic_memory.bas
Type Buffer
    Public:
        Declare Constructor(size As Integer)
        Declare Destructor()
        Declare Property Data() As Byte Ptr
    Private:
        buffer As Byte Ptr
        bufSize As Integer
End Type

Constructor Buffer(size As Integer)
    buffer = Allocate(size)
    bufSize = size
    Print "Allocated "; size; " bytes"
End Constructor

Destructor Buffer()
    If buffer Then
        Deallocate(buffer)
        Print "Freed "; bufSize; " bytes"
    End If
End Destructor

Property Buffer.Data() As Byte Ptr
    Return buffer
End Property

Scope
    Dim buf As Buffer = Buffer(1024)
    ' Use the buffer...
End Scope

这个 Buffer 类型管理动态内存分配。构造函数分配内存,而析构函数确保其被释放。这可以防止内存泄漏,即使发生异常或程序员忘记取消分配。

对象数组中的析构函数

当对象数组被销毁时,析构函数会自动为每个元素调用。

array_destructor.bas
Type Item
    Public:
        Declare Constructor(index As Integer)
        Declare Destructor()
    Private:
        itemIndex As Integer
End Type

Constructor Item(index As Integer)
    itemIndex = index
    Print "Item "; index; " created"
End Constructor

Destructor Item()
    Print "Item "; itemIndex; " destroyed"
End Destructor

Scope
    Dim items(1 To 5) As Item
    For i As Integer = 1 To 5
        items(i) = Item(i)
    Next
End Scope

当数组 items 超出范围时,析构函数会按照与构造顺序相反的顺序为每个元素调用。这演示了对象数组的自动清理。

继承中的析构函数

析构函数与继承一起工作,并按与构造顺序相反的顺序调用。

inheritance_destructor.bas
Type Base
    Public:
        Declare Constructor()
        Declare Destructor()
End Type

Constructor Base()
    Print "Base constructor"
End Constructor

Destructor Base()
    Print "Base destructor"
End Destructor

Type Derived Extends Base
    Public:
        Declare Constructor()
        Declare Destructor()
End Type

Constructor Derived()
    Print "Derived constructor"
End Constructor

Destructor Derived()
    Print "Derived destructor"
End Destructor

Scope
    Dim obj As Derived
End Scope

此示例展示了继承中的析构函数行为。当销毁 Derived 对象时,首先运行派生类的析构函数,然后是基类的析构函数。这确保了正确的清理顺序。

使用 Delete 手动销毁

可以使用 Delete 运算符为动态分配的对象显式调用析构函数。

manual_destructor.bas
Type ManagedResource
    Public:
        Declare Constructor()
        Declare Destructor()
End Type

Constructor ManagedResource()
    Print "Resource created"
End Constructor

Destructor ManagedResource()
    Print "Resource destroyed"
End Destructor

Dim res As ManagedResource Ptr = New ManagedResource
' Use the resource...
Delete res
Print "After deletion"

在这里,我们手动控制对象的生命周期。New 运算符创建对象,Delete 显式调用析构函数。这对于具有动态存储持续时间的对象很有用。

异常处理中的析构函数

即使发生异常,也会调用析构函数,从而确保资源清理。

exception_destructor.bas
Type SafeResource
    Public:
        Declare Constructor()
        Declare Destructor()
End Type

Constructor SafeResource()
    Print "SafeResource created"
End Constructor

Destructor SafeResource()
    Print "SafeResource destroyed"
End Destructor

Sub RiskyOperation()
    Dim res As SafeResource
    Print "About to throw exception"
    Error 999  ' Simulate an exception
End Sub

Try
    RiskyOperation()
Catch
    Print "Exception caught"
End Try

这表明在发生异常时的堆栈展开过程中会调用析构函数。尽管发生异常,SafeResource 对象仍得到正确清理,这表明了析构函数在异常安全方面的重要性。

文件处理中的析构函数

析构函数可以确保即使发生错误也能正确关闭文件。

file_destructor.bas
Type FileWrapper
    Public:
        Declare Constructor(fileName As String)
        Declare Destructor()
        Declare Function ReadLine() As String
    Private:
        fileNum As Integer
End Type

Constructor FileWrapper(fileName As String)
    fileNum = FreeFile()
    If Open(fileName For Input As #fileNum) Then
        Print "Failed to open file"
        fileNum = 0
    Else
        Print "File opened successfully"
    End If
End Constructor

Destructor FileWrapper()
    If fileNum Then
        Close #fileNum
        Print "File closed"
    End If
End Destructor

Function FileWrapper.ReadLine() As String
    If fileNum = 0 Then Return ""
    Line Input #fileNum, Result
    Return Result
End Function

Scope
    Dim file As FileWrapper = FileWrapper("test.txt")
    Print "First line: "; file.ReadLine()
End Scope

FileWrapper 类型安全地管理文件资源。构造函数打开文件,析构函数确保其关闭。即使在文件操作期间发生异常,这种模式也可以防止资源泄漏。

最佳实践

本教程介绍了 FreeBasic 的 Destructor 关键字,并通过实际示例展示了其在正确资源管理和清理方面的用法。

作者

我叫 Jan Bodnar,我是一名热情的程序员,拥有丰富的编程经验。我从 2007 年开始撰写编程文章。迄今为止,我已撰写了 1,400 多篇文章和 8 本电子书。我在教授编程方面拥有十多年的经验。

列出所有 FreeBasic 教程