类的构造函数
Object Pascal中的类有一种特殊的方法叫构造函数。
构造函数是一种用来建立实例类的方法。
构造函数用来初始化任何类成员变量,为类分配所必须的内存,或者做任何其他初始化工作。
在上一讲中定义的TVehicle就没有构造函数,若不提供一个构造函数,当建立类时,就会用隐藏的类构造程序(Object Pascal所有类都是从TObject 派生,TObject类有一个构造函数称Create,因此若不提供其他构造函数,一般就调用此构造程序。)虽然对于简单的类来说基本构造程序比较好,但一般总是要为具有一定意义的类提供一个构造函数。构造函数的取名时任意的,但必须用关键字constructor声明,这样就可以把它当做构造函数区别对待了,下面我们继续完善TVehicle类,增加一个构造函数。如下:
type TVehicle = class private CurrentGear: Integer; Started: Boolean; Speed: Integer; procedure StartElectricalSystem; procedure StartEngine; protected procedure StartupProcedure; public HaveKey: Boolean; Start: Boolean; procedure SetGear(Gear: Integer); procedure Accelerate(Acceleration: Integer); procedure Brake(Factor: Integer); procedure Turn(Direction: Integer); procedure ShutDown; constructor Create; { 构造函数} end;
特别注意,构造函数是一种特殊类型的方法,它没有返回类型。
类可以有不只一个构造函数,这可有两种不同的方式来实现:
1、 给构造函数以不同的名称,例如:
TVehicle = class { 省略其他部分内容} constructor Create; constructor CreateModel(Model: string);
2、 通过方法重载声明多重构造函数,构造函数拥有相同的函数名称,但具有不同的参数,例如:
TVehicle = class { 省略其他部分内容} constructor Create; overload; constructor Create(AOwner: TObject); overload; { overload重载}
通常构造函数用Create名称就足够了,重载Create的另一个原因是为了与C++ Builder相兼容。C++不允许构造函数的名称不同,因此必须使用重载来定义多个构造函数。
多重构造函数提供了建立类的不同方法。例如:一个类含有不带参数的构造函数,也可以含有带一个或者多个参数的构造函数,这些参数把字段初始化成一定的值。
再例如假设有一个TMyRect类,它是封装矩形的类。这个类有好几个构造函数,有一个缺省的构造函数,此构造函数用来把所有字段都设置为0,,另外一个用来设置类字段的构造函数。首先我们来看看这种类是如何声明的:
type TMyRect = class private Left: Integer; Top: Integer; Right: Integer; Bottom: Integer; public function GetWidth: Integer; function GetHeight: Integer; procedure SetRect(ALeft, ATop, ARight, ABottom: Integer); { 两个构造函数} constructor Create; { 此构造函数用来初始化所有字段为0} constructor CreateVal(ALeft, ATop, ARight, ABottom: Integer); { 此函数用来设置字段为特定值,其中的参数A开头的都是对于构造函数 来说,都是局部的,,都以A开头,用来区别局部变量和字段的。 以A开头是一种习惯。 } end;
构造函数的定义如下:
constructor TMyRect.Create; begin inherited Create; Left := 0; Top := 0; Right := 0; Bottom := 0; { 这里其实没有必要把每个字段初始化为0, 因为当建立一个类的对象时,所有字段都自动初始化为0 } end; constructor TMyRect.CreateVal(ALeft, ATop, ARight, ABottom: Integer); begin inherited Create; Left := ALeft; Top := ATop; Right := ARight; Bottom := ABottom; end;
Note
当建立一个类的对象时,所有字段都自动初始化为0。
实例化(Instantiation)就是创建被称为实例的类的对象。
如下:
var Rect1, Rect2: TMyRect; begin Rect1 := TMyRect.Create; { 0 * 0 的矩形} Rect2 := TMyRect.CreateVal(0, 0, 100, 100); { 100 * 100 大小的矩形} end.
TMyRect的两个实例都是动态分配内存的,所有的Object Pascal类都是建立在堆上的,所有的类变量因此也是指针。Rect1和Rect2变量都是指向TMyRect类的指针。上面的代码意味着内存的消耗,因此在end以前也应该有释放与这两个类实例有关的内存,下一讲中我们将讲到“类的析构函数”。
以上代码均在Delphi7中测试通过。