私がここで読んだように、
VMTには、親クラスリンク、インスタンスサイズ、クラス名、動的メソッドテーブル、公開メソッドテーブル、公開フィールドテーブル、RTTIテーブル、マジックフィールドの初期化テーブル、非推奨のOLEなどの機能をサポートする多数の「マジック」フィールドも含まれています。自動ディスパッチテーブルと実装されたインターフェイステーブル
VMTには、クラスが定義されているユニット名を含むフィールドが含まれていないようです。「コンパイラの魔法」が関係していますか?
VMTがここに関与する必要がある理由がわかりません。TObjectはすでにそのためのを公開しclass function UnitName
ています。
VMTには、クラスRTTI(ClassInfo
メソッドによって提供される)へのポインターが含まれています。クラスRTTIには、クラスユニット名が含まれています。演習として、VMTポインターからユニット名を取得できます。これを作成しました(Delphi XEでテスト済み)。
uses TypInfo;
type
TObj = class
end;
procedure TForm1.Button3Click(Sender: TObject);
var
Obj: TObj; // dummy obj instance
VMT: Pointer;
P: Pointer; // class info
begin
// you can get VMT pointer so
Obj:= TObj.Create;
VMT:= PPointer(Obj)^;
Obj.Free;
// or so
VMT:= Pointer(TObj);
P:= PPointer(PByte(VMT) + vmtTypeInfo)^;
if P <> nil then
ShowMessage(GetTypeData(P).UnitName);
end;
procedure MessageException(E: Exception);
var
TI: TypInfo.PTypeInfo;
begin
TI := E.ClassInfo;
if Assigned(TI) then
begin
Dialogs.MessageDlg(TypInfo.GetTypeData(TI).UnitName + '.' +
E.ClassName + ': ' + E.Message, Dialogs.mtError, [Dialogs.mbOK], 0, Dialogs.mbOK);
end
else
begin
Dialogs.MessageDlg(E.ClassName + ': ' + E.Message, Dialogs.mtError, [Dialogs.mbOK], 0, Dialogs.mbOK);
end;
end;
ClassInfoはnilについてテストする必要があることに注意してください。たとえば、SysUtils.ERangeErrorにはありません。