`
美丽的小岛
  • 浏览: 297799 次
  • 性别: Icon_minigender_1
  • 来自: 大连
社区版块
存档分类
最新评论

pascal学习小记(六)---VMT

 
阅读更多

今天看了《VCL》一章,感受很多,一般都学习JAVA的,对于面向对象用另外一个思维去解释的时候就显得有点不可以去适应了。

看了一下下午也只看了一个叫VMT的东西,虚拟方法表。明白了一个virtual与dynamic方法的区别。

相对来说,virtual占用的内存会很大比较多,每个子类都会把父类的的方法都列出来;对于dynamic就不会这样做的了,它只会把子类覆盖的放在VMT表中,其它的它会往上面找父类的方法。这个为VCL节省了很多内存。效率相对于virtual是相对慢了一点,可是节省了50%的空间,才拖延了3%的时间,很好的时间换空间的例子。



 内存的逻辑结构为:

 

 

 

实验代码:

unit fmMain;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, Buttons, ComCtrls, DB, DBTables, StdCtrls, ExtCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    CheckBox1: TCheckBox;
    RadioButton1: TRadioButton;
    ListBox1: TListBox;
    Memo1: TMemo;
    Button2: TButton;
    Button3: TButton;
    Database1: TDatabase;
    PageControl1: TPageControl;
    TabSheet1: TTabSheet;
    TabSheet2: TTabSheet;
    lbVMTs: TListBox;
    lbVMTContents: TListBox;
    BitBtn1: TBitBtn;
    BitBtn2: TBitBtn;
    Button4: TButton;
    Button5: TButton;
    procedure Button1Click(Sender: TObject);
    procedure CheckBox1Click(Sender: TObject);
    procedure RadioButton1Click(Sender: TObject);
    procedure ListBox1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure Memo1Click(Sender: TObject);
    procedure Button3Click(Sender: TObject);
    procedure BitBtn1Click(Sender: TObject);
    procedure Button4Click(Sender: TObject);
    procedure Button5Click(Sender: TObject);
  private
    { Private declarations }
    aClass : TClass;
    sClassName : String;

    procedure ShowVMTResult(const Msg: string);
    procedure ShowVMTEntry(const iDelta: Integer; pVMT: Pointer);
    procedure ShowVMTContent(aVMT: TClass);
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
begin
  aClass := Self.Button1.ClassType;
  sClassName := 'TButton';
end;

procedure TForm1.CheckBox1Click(Sender: TObject);
begin
  aClass := Self.CheckBox1.ClassType;
  sClassName := 'TCheckBox';
end;

procedure TForm1.RadioButton1Click(Sender: TObject);
begin
  aClass := Self.RadioButton1.ClassType;
  sClassName := 'TRadioButton';
end;

procedure TForm1.ListBox1Click(Sender: TObject);
begin
  aClass := Self.ListBox1.ClassType;
  sClassName := 'TListBox';
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  aClass := Self.ClassType;
  sClassName := 'TForm1';
end;

procedure TForm1.Memo1Click(Sender: TObject);
begin
  aClass := Self.Memo1.ClassType;
  sClassName := 'TMemo';
end;

procedure TForm1.Button3Click(Sender: TObject);
begin
  aClass := Self.Database1.ClassType;
  sClassName := 'TDatabase';
end;

procedure TForm1.BitBtn1Click(Sender: TObject);
begin
  ShowVMTContent(aClass);
end;

const
  VMTOFFSET = 12;
  VMTDELTA = 4;

procedure TForm1.ShowVMTContent(aVMT: TClass);
var
  pVMT : Pointer;
  idx : Integer;
begin
  ShowVMTResult(sClassName + ' VMT表格地址 : ' + IntToStr(Integer(aVMT)) );
  pVMT := Pointer(aVMT);
  idx := VMTOFFSET;
  while (idx > vmtSelfPtr) do
  begin
    ShowVMTEntry(idx, pVMT);
    Dec(idx, VMTDELTA);
  end;    // while
end;

procedure TForm1.ShowVMTEntry(const iDelta: Integer; pVMT: Pointer);
var
  pResult : Pointer;
  Msg : String;

  procedure DoProcess(const sName : String);
  begin
    if (Assigned(pResult)) then
    begin
      Msg := Format('%s : %x', [sName, Integer(pResult)]);
      ShowVMTResult(Msg);
    end;
  end;

begin
  pResult := Pointer(Integer(pVMT) + iDelta);
  case iDelta of    //
    vmtCreateObject : DoProcess('vmtCreateObject');
    vmtRelease : DoProcess('vmtRelease');
    vmtAddRef : DoProcess('vmtAddRef');
    vmtQueryInterface : DoProcess('vmtQueryInterface');
    vmtDestroy : DoProcess('vmtDestroy');
    vmtFreeInstance : DoProcess('vmtFreeInstance');
    vmtNewInstance : DoProcess('vmtNewInstance');
    vmtDefaultHandler : DoProcess('vmtDefaultHandler');
    vmtDispatch : DoProcess('vmtDispatch');
    vmtBeforeDestruction : DoProcess('vmtBeforeDestruction');
    vmtAfterConstruction : DoProcess('vmtAfterConstruction');
    vmtSafeCallException : DoProcess('vmtSafeCallException');
    vmtParent : DoProcess('vmtParent');
    vmtInstanceSize : DoProcess('vmtInstanceSize');
    vmtClassName : DoProcess('vmtClassName');
    vmtDynamicTable : DoProcess('vmtDynamicTable');
    vmtMethodTable : DoProcess('vmtMethodTable');
    vmtFieldTable : DoProcess('vmtFieldTable');
    vmtTypeInfo : DoProcess('vmtTypeInfo');
    vmtInitTable : DoProcess('vmtInitTable');
    vmtAutoTable : DoProcess('vmtAutoTable');
    vmtIntfTable : DoProcess('vmtIntfTable');
    vmtSelfPtr : DoProcess('vmtSelfPtr');
  end;    // case
end;

procedure TForm1.ShowVMTResult(const Msg: string);
begin
  Self.lbVMTs.Items.Add(Msg);
end;

procedure TForm1.Button4Click(Sender: TObject);
var
  aPnl : TPanel;
  aForm : TForm1;
begin
  aClass := aPnl.ClassType;
  sClassName := 'TPanel';
  ShowVMTContent(aClass);

  aPnl := TPanel.Create(Self);
  aClass := aPnl.ClassType;
  sClassName := 'TPanel';
  ShowVMTContent(aClass);
  FreeAndNil(aPnl);


end;

procedure TForm1.Button5Click(Sender: TObject);
var
  Msg : String;
  pVMT : Pointer;
begin
  Msg := Format('%s : %x', ['Self', Integer(Pointer(Self))]);
  ShowVMTResult(Msg);
  pVMT := Pointer(Integer(Pointer(Self)^) + vmtSelfPtr);
  Msg := Format('%s : %x', ['vmtSelfPtr', Integer(Pointer(pVMT))]);
  ShowVMTResult(Msg);
  pVMT := Pointer(Pointer(Integer(Pointer(Self)^) + vmtSelfPtr)^);
  Msg := Format('%s : %x', ['vmtSelfPtr', Integer(Pointer(pVMT))]);
  ShowVMTResult(Msg);
end;

end.

 

显示实验为:



 

  • 大小: 1.2 MB
  • 大小: 458.9 KB
  • 大小: 73.3 KB
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics