Delphi 系统[21]关键字和保留字 constructor、destructor、property - 构造函数,析构函数、属性
Delphi 系统[21]关键字和保留字 constructor、destructor、property - 构造函数,析构函数、属性
1、定义:
- constructor :声明或定义一个构造函数,可以用于类类型、对象类型、结构类型。 结构类型不允许定义无参数的构造函数。当类被实例化时, 首先调用此函数 ,构造函数一般用Create表示, Create方法能够连带类中存在的CreateWnd方法.
- destructor :声明或定义一个析构函数,可以用于类类型、对象类型。 析构函数主要用来释放对象资源。析构函数只允许覆盖,不允许重载。 在类被释放时自动调用,析构函数通常用Destroy作为函数名.
- property :声明或定义一个属性,可以用于类类型、对象类型、结构类型。属性分为显式属性和隐式属性两种,只有声明为 published 访问类型的属性才是显式属性,才可以直接在对象查看器中查看。 TEvent事件也是属性的一种,可以在 published 下用 property 进行声明。
2、示例:
{ 定义类类型 }
type
TMyObj = class(TObject)
private
FName: string;
FAge: Cardinal;
FOnTexChange: TEvent; { 事件 }
protected
public
constructor Create; { 构造函数 }
destructor Destroy; override; { 析构函数 }
published
property Name: string read FName write FName; { 发布属性 }
property Age: Cardinal read FAge write FAge;
{ 发布事件 TEvent}
property OnTextChange: TEvent read FOnTexChange write FOnTexChange;
end;
---------------------------------------------------------------------------------------
{ 定义结构类型 }
type
MyRec = record
private
FName: string;
FAge: Cardinal;
public
constructor Create(Name: string); { 构造函数 }
{ 这里不能有析构函数 }
property Age: Cardinal read FAge write FAge; { 公开属性 }
end;
---------------------------------------------------------------------------------------
{ 定义对象类型 }
type
MyObj = object
private
FName: string;
FAge: Cardinal;
protected
public
constructor Create; { 构造函数 }
destructor Destroy; override; { 析构函数 }
{ 公开属性 }
property Name: string read FName write FName;
property Age: Cardinal read FAge write FAge;
end;
3、关于 Constructors 的一些说明:
构造函数是一种创建和初始化实例对象的特殊方法。构造函数的声明看起来像过程声明,但它以单词constructor开头。示例:
constructor Create;
constructor Create(AOwner: TComponent);
构造函数必须使用默认的寄存器调用约定。尽管声明未指定返回值,但构造函数返回对其创建或调用的对象的引用。
一个类可以有多个构造函数,但大多数都只有一个。通常调用构造函数Create。
要创建对象,请对类类型调用构造函数方法。例如:
MyObject := TMyClass.Create;
这将为堆上的新对象分配存储,将所有序号字段的值设置为零,将nil分配给所有指针和类类型字段,并使所有字符串字段为空。接下来执行构造函数实现中指定的其他操作;通常,根据作为参数传递给构造函数的值初始化对象。最后,构造函数返回对新分配和初始化对象的引用。返回值的类型与构造函数调用中指定的类类型相同。
如果在类引用上调用的构造函数执行期间引发异常,则会自动调用销毁析构函数来销毁未完成的对象。
当使用对象引用(而不是类引用)调用构造函数时,它不会创建对象。相反,构造函数对指定的对象进行操作,只执行构造函数实现中的语句,然后返回对该对象的引用。构造函数通常在对象引用上与继承的保留字一起调用,以执行继承的构造函数。
下面是一个类类型及其构造函数的示例:
type
TShape = class(TGraphicControl)
private
FPen: TPen;
FBrush: TBrush;
procedure PenChanged(Sender: TObject);
procedure BrushChanged(Sender: TObject);
public
constructor Create(Owner: TComponent); override;
destructor Destroy; override;
...
end;
constructor TShape.Create(Owner: TComponent);
begin
inherited Create(Owner); // 初始化继承的部分 Initialize inherited parts
Width := 65; // 更改继承的属性 Change inherited properties
Height := 65;
FPen := TPen.Create; // 初始化新字段 Initialize new fields
FPen.OnChange := PenChanged;
FBrush := TBrush.Create;
FBrush.OnChange := BrushChanged;
end;
构造函数的第一个操作通常是调用继承的构造函数来初始化对象的继承字段。然后,构造函数初始化子类中引入的字段。因为构造函数总是清除它为新对象分配的存储,所以所有字段都以零值(序号类型)、nil(指针和类类型)、empty(字符串类型)或Unassigned(变量)开头。因此,除了非零值或非空值之外,无需在构造函数的实现中初始化字段。
当通过类类型标识符调用时,声明为虚拟的构造函数等价于静态构造函数。然而,当与类引用类型结合使用时,虚拟构造函数允许对象的多态构造——也就是说,构造在编译时类型未知的对象。
4、关于destructor的一些说明:(2022.12.13 滔Roy)
析构函数是一种特殊的方法,它在调用对象时销毁对象并释放其内存。析构函数的声明看起来像过程声明,但它以析构函数一词开头。例子:
destructor SpecialDestructor(SaveData: Boolean);
destructor Destroy; override;
析构函数必须使用默认的寄存器调用约定。虽然一个类可以有多个析构函数,但建议每个类重写继承的Destroy方法,不声明其他析构函数。
要调用析构函数,必须引用实例对象。例如
MyObject.Destroy;
调用析构函数时,首先执行析构函数实现中指定的操作。通常,这包括销毁任何嵌入对象并释放对象分配的资源。然后,为该对象分配的存储被释放。
这里是一个析构函数实现的示例
destructor TShape.Destroy;
begin
FBrush.Free;
FPen.Free;
inherited Destroy;
end;
析构函数实现中的最后一个操作通常是调用继承的析构函数来销毁对象的继承字段。
当在创建对象期间引发异常时,将自动调用Destroy来处理未完成的对象。这意味着销毁必须准备好处理部分构建的对象。由于构造函数在执行其他操作之前将新对象的字段设置为零或空值,因此部分构造对象中的类类型和指针类型字段始终为零。因此,在对类类型或指针类型字段进行操作之前,析构函数应该检查nil值。调用Free方法(在TObject中定义)而不是Destroy,提供了一种在销毁对象之前检查nil值的方便方法。
constructor TObject.Create;
begin
end;
destructor TObject.Destroy;
begin
end;
procedure TObject.Free;
begin
if Self <> nil then
Destroy;
end;
创建时间:2021.08.12 更新时间:2022.12.13