Delphi中類的VMT

TObject是全部對象的基本類,DELPHI中的任何對象都是一個指針,這個指針指明該對象在內存中所佔據的一塊空間!   
   對象空間的頭4個字節是指向該對象類的虛方法地址表(VMT-Vritual   Method   Table)。接下來的空間就是存儲對象自己成員數據的空間,並按從該對象最原始祖先類的數據成員到該對象類的數據成員的總順序,和每一級類中數據成員的定義順序存儲。   
  類的虛方法地址表(VMT)保存從該類的原始祖先類派生到該類的全部類的虛方法的過程地址。   
  即便,咱們本身並未定義任何類的虛方法,但該類的對象仍然存在指向虛方法地址表的指針,只是地址項的長度爲零。但是,在TObject中定義的那些虛方法,如Destroy、FreeInstance等等,又存儲在什麼地方呢?原來,他們的方法地址存儲在相對VMT指針負方向偏移的空間中。其實,在VMT表的負方向偏移76個字節的數據空間是對象類的系統數據結構,這些數據結構是與編譯器相關的,而且在未來的DELPHI版本中有可能被改變。   
  VMT是一個從負偏移地址空間開始的數據結構,負偏移數據區是VMT的系統數據區,VMT的正偏移數據是用戶數據區(自定義的虛方法地址表)。TObject中定義的有關類信息或對象運行時刻信息的函數和過程,通常都與VMT的系統數據有關,事實上,self之上就是RTTI信息。   
  一個VMT數據就表明一個類,其實VMT就是類!在Object   Pascal中咱們用TObject、TComponent等等標識符表示類,它們在DELPHI的內部實現爲各自的VMT數據。而用class   of保留字定義的類的類型,實際就是指向相關VMT數據的指針。   
  對咱們的應用程序來講,VMT數據是靜態的數據,當編譯器編譯完成咱們的應用程序以後,這些數據信息已經肯定並已初始化。咱們編寫的程序語句可訪問VMT相關的信息,得到諸如對象的尺寸、類名或運行時刻的屬性資料等等信息,或者調用虛方法或讀取方法的名稱與地址等等操做。當一個對象產生時,系統會爲該對象分配一塊內存空間,並將該對象與相關的類聯繫起來,因而,在爲對象分配的數據空間中的頭4個字節,就成爲指向類VMT數據的指針。 數據結構

   //建立一個對象   obj   :=   TObject.Create;   
  1)   用   TObject   對應的   VMT   爲依據,調用   TObject   的   Create   構造函數。   
  2)   而在   Create   構造函數調用了系統的   _ClassCreate   過程,   
  3)   系統的   ClassCreate   過程又經過類   VMT   調用   NewInstance   虛方法。   
  4)   調用   NewInstance   方法的目的是要創建對象的實例空間,由於咱們沒有重載該方法,因此,   
        它就是   TObject   類的   NewInstance。   
  5)   TObjec   類的   NewInstance   方法將根據編譯器在VMT表中初始化的對象實例尺寸(InstanceSize),   
        調用   GetMem   過程爲該對象分配內存,   
  6)   而後調用   InitInstance   方法將分配的空間初始化。   
  7)   InitInstance方法首先將對象空間的頭4個字節初始化爲指向對象類對應VMT的指針,而後將其他的空間清零。   
  8)   創建對象實例以後,還調用了一個虛方法AfterConstruction。   
  9)   最後,將對象實例數據的地址指針保存到AnObject變量中,這樣,obj   對象就誕生了。   
  //消滅一個對象     Obj.Destroy;   
          TObject的析構函數Destroy被聲明爲虛方法,它也是系統固有的虛方法之一。   
  1)   Destory方法首先調用了   BeforeDestruction   虛方法,   
  2)   而後調用系統的   _ClassDestroy過程。   
  3)   _ClassDestory   過程又經過類VMT調用   FreeInstance   虛方法,   
  4)   由FreeInstance方法調用FreeMem過程釋放對象的內存空間。函數

  就這樣,一個對象就在系統中消失。在對象的構造和析構過程當中,調用了NewInstance和FreeInstance兩個虛函數,來建立和釋放對象實例的內存空間。之因此將這兩個函數聲明爲虛函數,是爲了能讓用戶在編寫須要用戶本身管理內存的特殊對象類時(如在一些特殊的工業控制程序中),有擴展的空間。   
  而將AfterConstruction和BeforeDestruction聲明爲虛函數,也是爲了未來派生的類在產生對象以後,有機會讓新誕生的對象呼吸第一口新鮮空氣,而在對象消亡以前能夠容許對象完成善後事宜,這都是合情合理的事。其實,TForm對象和TDataModule對象的OnCreate事件和OnDestroy事件,就是在TForm和TDataModule重載的這兩個虛函數過程分別觸發的。   
  TObject的構造函數Create和析構函數Destory居然沒有寫任何代碼,其實,在調試狀態下,經過Debug的CPU窗口,可清楚地反映出Create和Destory的彙編代碼。由於,締造DELPHI的大師門(Hejlsberg...)不想將過多複雜的東西提供給用戶,他們但願用戶在簡單的概念上編寫應用程序,將複雜的工做隱藏在系統的內部由他們承擔。因此,在發佈System.pas單元時特別將這兩個函數的代碼去掉,讓用戶認爲TObject是萬物之源,用戶派生的類徹底從虛無中開始,這自己並無錯。   
  雖然,閱讀DELPHI的這些最本質的代碼須要少許的彙編語言知識,但閱讀這樣的代碼,可讓咱們更深入認識DELPHI世界的起源和發展的基本規律。即便看不太懂,能起碼瞭解一些基本東西,對咱們編寫DELPHI程序也是大有幫助。   
      那是虛擬方法表在內存中的狀況,能夠清楚的看到   self(此 self 指對象的self)   指針就指向了虛擬方法表的入口,而   self (此 self 指類的self)  指針則位於虛擬方法表的入口地址-76的位置。   
  固然這不具備通用性,由於在未來的delphi版本這個位置可能會變.   
      self之上就是RTTI信息。因此delphi實現RTTI是與C++不一樣的,C++靠宏。   
  Delphi則依靠編譯器,是與delphi當前版本的編譯器緊密相關的。   
  不過反正作Pascal編譯器的就Borland一家.....  spa

  虛擬方法表:$   system.pas   
  {   Virtual   method   table   entries   }   
      vmtSelfPtr                       =   -76;   
      vmtIntfTable                   =   -72;   
      vmtAutoTable                   =   -68;   
      vmtInitTable                   =   -64;   
      vmtTypeInfo                     =   -60;   
      vmtFieldTable                 =   -56;   
      vmtMethodTable               =   -52;   
      vmtDynamicTable             =   -48;   
      vmtClassName                   =   -44;   
      vmtInstanceSize             =   -40;   
      vmtParent               =   -36;   
      vmtSafeCallException   =   -32;   
      vmtAfterConstruction   =   -28;   
      vmtBeforeDestruction   =   -24;   
      vmtDispatch                     =   -20;   
      vmtDefaultHandler         =   -16;   
      vmtNewInstance               =   -12;   
      vmtFreeInstance             =   -8;   
      vmtDestroy                       =   -4;   
      vmtQueryInterface         =   0;   
      vmtAddRef                         =   4;   
      vmtRelease                       =   8;   
      vmtCreateObject             =   12;指針

}調試

相關文章
相關標籤/搜索