全國最多中醫師線上諮詢網站-台灣中醫網
發文 回覆 瀏覽次數:1553
推到 Plurk!
推到 Facebook!

Delphi 實作 TForm 時, TApplication.CreateForm 的內容就有這樣

 
jackkcg
站務副站長


發表:891
回覆:1050
積分:848
註冊:2002-03-23

發送簡訊給我
#1 引用回覆 回覆 發表時間:2002-07-20 04:51:23 IP:61.70.xxx.xxx 未訂閱
此為轉載文章 一般我們在呼叫 Class 的 Constructor 時會建立此 Class 的物件實體。但是,如果我們 再次呼叫此物件實體的 Constructor 時,那麼會發生什麼事情呢?是只會單純的執行 Constructor 的內容而已,還是會再產生另一個物件實體呢?例如 Delphi 實作 TForm 時, TApplication.CreateForm 的內容就有這樣的現象,它是在做什麼事情呢?以下為其這段的程式內容: procedure TApplication.CreateForm(InstanceClass: TComponentClass; var Reference); var Instance: TComponent; begin Instance := TComponent(InstanceClass.NewInstance); TComponent(Reference) := Instance; try Instance.Create(Self); ^^^^^^^^^^^^^^^^^^^^^^ except TComponent(Reference) := nil; raise; end; if (FMainForm = nil) and (Instance is TForm) then begin TForm(Instance).HandleNeeded; FMainForm := TForm(Instance); end; end; 解答 你問的問題相當有深度,但在進入主題前,首先我們必須瞭解,Object Pascal 所採用的物件模型是「物件參照模型」(Object reference Model)。所謂的「參照」(reference) 是相當類似指標 (pointer) 的一種技術,由記憶體配置一個位置,而參考到實際儲存資料的地方,並進而藉由此參照去操作實際儲存資料位置內的資料。當我們在 Delphi 中宣告一個物件變數,例如 var obj: TForm; 此時僅是宣告 obj 是 TForm 此類別型態的變數,而此時你尚無法使用這個變數,因為在物件參照模型下,每一個物件實際上是動態的被配置在堆積 (heap) ,類別型態變數 (如上述的 obj) 僅是參考到在這記憶體中物件的一個位置代碼 (handle)。因此在我們要使用物件變數 (它僅是個參照,而非物件) 前,必須為這個物件實際配置記憶體。 接著下面這段敘述 obj := TForm.create(nil); 就是完成物件記憶體的配置,並將其位置傳回給 obj,所以在我們操作 obj 時,就不會為存取不到物件而發生 Access xxxx ... 錯誤的訊息而發窘。那麼呼叫 create 會發生什麼事?根據類別型態的不同,會產生不同的結果,但是有一件共通的事情是,它們一定會去執行 TObject (這是 VCL 架構下所有物件的元祖) 的 NewInstance、InitInstance 等動作,有興趣你可以去看看它的原始程式碼,執行這些動作為何?簡單的說,就是配置並初始化物件的記憶體空間,你可以看 Delphi 的 Help 說明。完成物件記憶體配置後,接下來當然要對此記憶體的內容加以潤飾一番 (如同帶入一些必要的資料),例如 TForm 就必須向 Windows 作業系統註冊並配置所需資源...等工作,這也就是 create 後面的動作,雖然建構的過程相當快,但卻十分複雜。 如果上面所講的你都可以接受,那麼後面所要談的就不至於有什麼大問題。TApplication 的 CreateForm 此方法需要兩個參數,一個是 TComponentClass 這個超類別型態的變數,及一個物件變數。TComponentClass 的宣告如下: TComponentClass = class of TComponent; 這代表它是 TComponent 的 MetaClass,換言之為 TComponent的類別參照型態 (你可以看 Delphi 有關 class of 語法的 Help 說明),通常我們稱它為超類別或母類別,但與父類別的意思又有所不同。它很有用,你可以將相容 TComponent 的類別當作參數傳送過來,當然 TForm 符合這項條件。所以當 Application.CreateForm(TForm1, Form1); 被執行時,TForm1=class(TForm),而 Form1 為 TForm1 型態的物件變數,此時 InstanceClass 相當於 TForm1,而 Reference 同等於 Form1 (因為它是以傳址的方式傳遞參數)。往下這一段: Instance := TComponent(InstanceClass.NewInstance); 相當於以下這一段 Instance := TComponent(TForm1.NewInstance); 此動作配置物件的記憶體並初始化此記憶體,並將位置傳回,其中由於 Instance 宣告的型態與傳回型態不同,因此必須進行型態轉換。接著將 Instance 的值指定給 Reference,此時 Instance 與 Reference 參照到同樣的物件空間。但是,不要忘記了,雖然位置空間已經配置並完成初始化,但裡面的內容含必要的資源並未建立,因此 Instance.Create(Self); 就是執行這件事情。由於物件空間已經具有,所以程式不會重複建構這個空間。但是,若對已經完成內容及資源皆建置的物件,再執行一次 Craete 的動作,例如 obj := TForm1.Create(self); .. obj.Create(self); <--- 產生錯誤 由於其內容及相關資源已經完成,對大多數類別而言(例如 TComponent 含其延伸類別),這個動作是不正確的。當你建構物件時你可以這樣做: obj := TForm1(TForm1.NewInstance); obj.Create(Self); obj.Show; 但我想大多數的人不會這般無聊,自尋麻煩吧!
------
**********************************************************
哈哈&兵燹
最會的2大絕招 這個不會與那個也不會 哈哈哈 粉好

Delphi K.Top的K.Top分兩個字解釋Top代表尖端的意思,希望本討論區能提供Delphi的尖端新知
K.表Knowlege 知識,就是本站的標語:Open our mind
系統時間:2024-05-15 7:25:22
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!