通過實驗,答案是肯定的!這使我感到很興奮,因為Delphi從誕生之日起,就限定了只能繼承於TObject的堆對象,必須通過Create和Free來建立和銷毀一個對象,而不能使用棧對象。而棧對象的好處就在於它能和其它類型一樣很方便的定義,它能自動調用構造函數和析構函數,在作用域范圍內(如函數內的局部對象)不必當心對象的建立和銷毀問題。要是Delphi具有了該功能,無意是Delphi編程者們的福音。
不過,進一步的測試卻比較失望,請看下面的代碼:
type
TMyRecord = record
private
x: Integer;
y: Integer;
public
// error: Parameterless constructors not allowed record types
// constructor Create;
// error: A record cannot introduce a destructor
// destructor TMyRecird;
constructor Create(a: Integer);
constructor TMyRecord; overload;
constructor TMyRecord(a, b: Integer); overload;
// constructor TMyRecord(a, b: Integer);
procedure Display;
property xi: Integer read x;
end;
{ TMyRecord }
constructor TMyRecord.Create(a: Integer);
begin
x := a;
y := 0;
end;
procedure TMyRecord.Display;
begin
ShowMessage(Format('x = %d, y = %d', [x, y]));
end;
constructor TMyRecord.TMyRecord;
begin
x := 0;
y := 0;
end;
constructor TMyRecord.TMyRecord(a, b: Integer);
begin
x := a;
y := b;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
rec: TMyRecord;
begin
rec.TMyRecord(100, 200);
rec.Display;
end;
可以看出,確實可以和C++一樣定義一個局部record對象(不需要動態建立),而且可以使用該對象的方法和屬性,請看TForm1.Button1Click方法的匯編碼(CPU調試窗口粘貼下來的):
Unit1.pas.72: begin
0045ACDC 83C4F8 add esp,-$08
Unit1.pas.73: rec.TMyRecord(100, 200);
0045ACDF 8BC4 mov eax,esp
0045ACE1 B9C8000000 mov ecx,$000000c8
0045ACE6 BA64000000 mov edx,$00000064
0045ACEB E8E4FFFFFF call TMyRecord.TMyRecord
Unit1.pas.74: rec.Display;
0045ACF0 8BC4 mov eax,esp
0045ACF2 E855FFFFFF call TMyRecord.Display
Unit1.pas.75: end;
0045ACF7 59 pop ecx
0045ACF8 5A pop edx
0045ACF9 C3 ret
從匯編碼中看,定義的TMyRecord變量rec確實是標准C++棧對象一樣的,在調用其方法的時候也隱含傳遞了Self指針(mov eax,esp),也就是說,rec在這裡已經區別於普通的record變量,而是一個實實在在的“對象”變量!
但是遺憾的是,它不能定義destructor方法,雖然可以定義constructor方法(不能定義為Tobject缺省的Create方法,帶參數可以),但卻不能在定義的時候自動調用構造方法(我原本以為和C++一樣,定義一個和TMyRecord同名的constructor方法,可以自動調用的),如此一來,靜態棧對象的主要優點就喪失了,如果手工調用構造方法,和定義一個普通record變量,然後調用靜態過程沒什麼兩樣了。其實,Delphi已經把record改道這一步了,稍稍進一步就可以完完全全的使用棧對象,從技術上講一點難度都沒有,編譯器只需要在棧中分配對象變量內存和銷毀對象變量內存的同時,隱含調用一下構造方法和析構方法就可以了的。
雖然很遺憾,但是還是為Delphi的這點進步而高興,至少我們可以利用這一功能封裝record,而且使用這有限的棧對象可以不用當心對象本身的銷毀問題(record對象中動態分配的內存還是得手工釋放或者調用它的某個方法釋放)。
後記:以前在DOS下,以C/C++為主,Pascal只用過Turbo Pascal4.0,對以後Pascal的版本並不十分了解,今天看了網友housisong的留言,才知道我所謂的新功能--有限棧對象,Delphi中早就有了,如Delphi7.0就可以使用Object關鍵字定義棧對象,而且比2007的record類型還完善一些,record不能繼承,而object對象能夠繼承,看來我真是孤陋寡聞了!!!