procedure TForm1.Button1Click(Sender: TObject);
var
line,line2:TLine;
begin
line:=TLine(Tshape.Create);
//转换的只是对象的引用的类型,从下面的测试结果可以得出实际的对象还是Tshape对象
line2:=TLine.Create;
//但是--> 问题2. 下面又如何解释?
Line.bp:=point(2,3);
line.ai:=999;
showmessage(format('line.bp:%d,%d: line.ai is %d',[Line.bp.X,Line.bp.y,line.ai]));
// 输出的是line.bp:2,3 line ai is 999
// 说明ai,bp并不是占用相同的内存空间,这样的话与上面的自相矛盾呀!!!
////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////
这个问题并不难理解,事实上程序没有出问题是因为后面创建了一个对象,注意不一定是TLine对象,任何对都可以.甚至可以不用一个变量,比如你只是写一句TObject.Create在Line2:=TLine.Create的位置.
事实上如果把TLine.Create一句去掉,程序也是运行正确的,显示也是正确的,但是我们定义一个字符串变量s,并在 line.ai:=999;一句的下面加入SetLength(s,10);
然后再看看showmessage(format('line.bp:%d,%d: line.ai is %d',[Line.bp.X,Line.bp.y,line.ai]));喝喝你看到什么了,显示的值是就不对了,为什么呢?是因为bp所占的内存空间本身就不是Line对象的,但是是本应用程序可用(至于是哪个变量所用或者其他东东所用就不得而知了),所以给它赋值不会造成错误,但是假如已经被其他部份占用,它就会改写其他部份的值(就比如你的程序中的Line2对象),而如果没有其他地方占用,并且后面存在着分配堆内存的操作,那它也会被赋盖掉.就比如上面的TObject.Create或者SetLength(s,10);
你也许会试一下,下面的代码也会得到正确结果:
line:=TLine(Tshape.Create);
line2:=TLine.Create;
Line.bp:=point(2,3);
line.ai:=999;
line2.ai:=99999;
showmessage(format('line.bp:%d,%d: line.ai is %d,Line2.ai is %d',[Line.bp.X,Line.bp.y,line.ai,line2.ai]));
// 输出的是line.bp:2,3 line ai is 999,Line2.ai is 99999
看起来好象说明Line2也并没有被占用.
事实上是被占用了的,不信?你调用Line2.Draw试试?会出错?为什么,因为Line2的RTTI已经被破坏了.
我们在后面加入下面一段代码:
p:=Pointer(Line2);
For i:=0 to 100 do
begin
s:=s+' '+IntToStr(p^);
if (i+1) MOD 10 = 0 then
s:=s+#13;
inc(p);
end;
Application.MessageBox(PChar(s),'',0);
显示的结果应该是Line2在内存中的数据的整数表示,按照VTM的结构,第一个整数应该是一个比较大的整数,是一个指针,指向RTTI,可是这里是3,说明Line.bp中的y占用了Line2的RTTI指针,按照这个说法,我们是肯定不能再调用Line2.Draw了,试验结果肯定了这一说法.
全部代码如下:
procedure TForm1.Button1Click(Sender: TObject);
var
line,line2:TLine;
p
Integer;
i:Integer;
s:String;
begin
line:=TLine(Tshape.Create);
line2:=TLine.Create;
Line.bp:=point(2,3);
line.ai:=999;
line2.ai:=99999;
showmessage(format('line.bp:%d,%d: line.ai is %d,line2.ai is %d',[Line.bp.X,Line.bp.y,line.ai,line2.ai]));
// 输出的是line.bp:2,3 line ai is 999,line2.ai is 99999
p:=Pointer(Line2);
For i:=0 to 100 do
begin
s:=s+' '+IntToStr(p^);
if (i+1) MOD 10 = 0 then
s:=s+#13;
inc(p);
end;
Application.MessageBox(PChar(s),'',0);
//输入出的前两个整数是3,99999
line2.draw;
end;
////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////
以上代在Delphi5/6/7中均测试过.