TObject中的ClassParent是一个很让人感兴趣的方法。通过这个方法,你可以从某个类开始,层层上溯,一直到整个VCL的根TObject为止,描述出一个完整的层次列表。可以用下面的例子来检查类继承关系:
procedure TForm1.Button1Click(Sender: TObject);
var
CurrObject : TObject;
CurrClass : TClass;
begin
CurrObject := Sender;
while CurrObject<>nil do begin
Memo1.Lines.Add( 'Class name is ' + CurrObject.ClassName );
Memo1.Lines.Add( 'Instance Size is ' + IntToStr(CurrObject.InstanceSize) );
Memo1.Lines.Add( '' );
CurrClass := CurrObject.ClassParent;
if CurrClass<>nil then
CurrObject := CurrClass.NewInstance
Else
CurrObject := nil;
end;
end;
注意上面的代码实际上是有问题的---用了NewInstance而没有释放。不过作为示例就不必再复杂化了,了解用法即可。
上面例子的输出:
ClassName is TButton
Instance Size is 536
Class name is TButtonControl
Instance Size is 524
Class name is TWinControl
Instance Size is 516
Class name is TControl
Instance Size is 348
Class name is TComponent
Instance Size is 48
Class name is TPersistent
Instance Size is 4
Class name is TObject
Instance Size is 4
可以看到,TObject和TPersistent都是不包含任何成员变量的(4个字节用于VTbl)。同时可以看到,TControl和TWinControl都是相当大的类,其中一定增加了不少成员变量。而一个TButton占用的内存多达536个字节,也就是说,2个按钮就要超过1K,这多少让人有点吃惊。(如果你想用SizeOf的话,不会得到正确的结果:所有的对象用Sizeof得到的结果都是4,这说明所谓的对象其实都是指针而已。)看来虽说现在内存越来越大,但是一个窗体上的构件还是不要太多的为好。
由于TButton占用的内存之大出乎意外,所以我又作了个程序,把常用的几十种构件都放了进去,看看占用的内存大小如何。代码很简单:
procedure TForm1.FormCreate(Sender: TObject);
var
i : integer;
Item : TListItem;
Size : integer;
begin
for i:=0 to ComponentCount-1 do begin
Item := ListView1.Items.Add;
Item.Caption := Components[i].ClassName;
Size := Components[i].InstanceSize;
Item.SubItems.Add( IntToStr(Size) );
end;
end;
从结果来看,大致可以得出如下的结论:
1.非窗口构件(如TShape,TBevel)的InstanceSize大多在300多个字节;
2.基本的窗口化构件(如TButton,TEdit,TListBox)的InstanceSize大多在500到600多个字节,属于Common Control的占用量还要更多一些;
3.各种各样的网格构件(TStringGrid,TDrawGrid)占用空间都比较大(700多个字节),TDBGrid甚至达到了800个字节。
4.各种和数据库相关的构件都比较大,一般在700多到900字节不等,只有TDataSource出乎意料的小—88个字节。
5.包括上面说到的TDataSource在内,还有几个构件也非常之小,它们是TMainMenu, TActionList,TCustomizeDlg,TTimer和TDataSource,只有80-90多个字节,而其他构件最少也有300多个字节。我没有找到哪个构件的大小在100-300字节这个区间。
6.在我测试到所有构件中,其InstanceSize最大的是TChart,达到了1024个字节。
7.新增的ShellListView和ShellTreeView也是消耗内存的大户,ShellTreeView消耗的字节数达到968字节,仅次于TChart而位居亚军。
不知道你看了这个结果有何感想,我想Delphi之所以这么消耗内存和启动速度比较慢大概也是因为这个原因吧,总之构件虽好,也不可以滥用就是了。