负责对象的创建和销毁。
概观
宣言
默认构造函数
复制构造函数
调用构造函数
概观
构造函数和析构函数分别负责创建和销毁对象。一般来说,构造函数给对象的初始状态,也就是给对象的成员数据赋予有意义的值。破坏者执行相反的功能;他们确保其对象所拥有的任何资源被正确地释放。
简单地说,构造函数是在创建对象时调用的特殊成员过程,析构函数是在对象被销毁时调用的特殊成员过程。无论是使用
Dim还是
New关键字显式地创建或销毁对象,编译器都会自动调用这两个构造函数和析构函数,或者通过将值传递给过程或通过对象进行隐式传递超出范围。
宣言
默认构造函数
默认构造函数是没有参数的构造函数,或者它们的所有参数都具有默认值。当定义对象但未初始化对象时,它们被调用,或者作为数组的一部分使用
Dim,
ReDim或
New[]关键字进行调用。在下面的示例中声明的第一个构造函数是一个默认构造函数。
复制构造函数
复制构造函数是从相同类型的另一个对象(或可转换为该类型的对象)创建或克隆对象时调用的构造函数。当使用另一个对象初始化一个对象时,或者通过将值传递给一个过程来隐含地显式地发生这种情况。声明复制构造函数有一个参数:通过引用传递的相同类型的对象。
仅在创建和初始化对象实例时调用复制构造函数。对象的赋值由
Member 操作符 Let处理。
调用构造函数
与其他成员过程不同,构造函数通常不直接从对象实例调用。相反,构造函数在
Dim语句中指定,具有初始化程序或没有一个,或在带有或不带参数的
New语句中。
当指定对象的初始化程序时,使用所需的类型跟随任何参数的名称。
Type foo
'' Declare a default ctor, copy ctor and normal ctor
Declare Constructor
Declare Constructor (ByRef As foo)
Declare Constructor (As Integer)
'' Declare a destructor
Declare Destructor
ints As Integer Ptr
numints As Integer
End Type
'' Define a constructor that creates 100 integers
Constructor foo
ints = New Integer(100)
numints = 100
End Constructor
'' Define a constructor that copies the integers from another object
Constructor foo (ByRef x As foo)
ints = New Integer(x.numints)
numints = x.numints
End Constructor
'' Define a constructor that creates some integers based on a parameter
Constructor foo (n As Integer)
ints = New Integer(n)
numints = n
End Constructor
'' Define a destructor that destroys those integers
Destructor foo
Delete[] ints
End Destructor
Scope
'' calls foo's default ctor
Dim a As foo
Dim x As foo Ptr = New foo
'' calls foo's copy ctor
Dim b As foo = a
Dim y As foo Ptr = New foo(*x)
'' calls foo's normal ctor
Dim c As foo = foo(20)
Dim z As foo Ptr = New foo(20)
'' calls foo's dtor
Delete x
Delete y
Delete z
End Scope '' <- a, b and c are destroyed here as well
编译器提供的构造函数和析构函数
如果没有为
Type或
Class声明复制构造函数,编译器将提供一个。如果没有声明构造函数,编译器还提供一个默认构造函数。
编译器提供的默认构造函数将成员数据初始化为默认值,即数字和指针成员设置为零(0),对象成员是默认构造的。编译器声明的复制构造函数将所有成员数据从一个类型复制到另一个类型:数字和指针类型使用复制对象中的对应数据成员进行初始化,对象成员由其对应的对象成员进行复制。这意味着动态资源(如指针数据成员所指向的内存)不被复制;只有地址被复制。因此,如果一个对象拥有一个资源,意味着它负责其创建和销毁,那么编译器生成的拷贝构造函数将是不够的。
如果未声明析构函数,则编译器将生成一个析构函数。这个析构函数调用对象成员的析构函数,对数组和指针类型不做任何操作。再次,如果对象拥有一个动态资源,那么编译器生成的析构函数就不足够了,因为当对象被破坏时资源将不被释放。
这通常被称为“规则3”:如果一个对象需要一个自定义的拷贝构造函数,赋值运算符或者析构函数,那么这三个函数就有可能需要。