DELPHI 對象的本質 VMT

來源:互聯網
上載者:User

標籤:sel   tde   lease   htm   而在   win   彙編   通用   except   

http://www.cnblogs.com/little-mat/articles/2206627.html

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一家.....  

  虛擬方法表:$   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;

}

 

參考資料:   
  1   <天方夜談VCL>   
  2   <Delphi的原子世界> 

DELPHI 對象的本質 VMT

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.