更新歷史:No.2
更新時間:2001-10-21 02:42
更新人員:Musicwind®
更新備註:修改格式。
更新歷史:No.1
更新時間:2001-10-19 21:15
更新人員:Musicwind®
更新備註:建立。
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~
前言:沉浸於Delphi已逾三載,可是每每翻閱Delphi的幫助文檔,還是會有許多收穫,於是不免感慨Delphi的博大!在慚愧之餘,將些許心得和收穫整理,與諸位當中如我般自大而學識尚淺者,共勉。
1.什麼是沉默的異常? (為什麼不是沉默的羔羊?;- ))
沉默的異常,即Slient Exceptions ,指的是缺省情況下不會出現討厭的訊息提示框的異常類型: EAbort 。在Object Pascal中,異常類別EAbort是所有沉默的異常類別的祖先類別(而EAbort是繼承Exception而來)。引發(Raise)一個EAbort將導致一個執行模組的停止,直到有最外層的異常處理模組截獲它,但是並不因此出現帶有紅色停止標誌的消息框。參考如下程式碼:
try
ShowMessage('Hello1');
Raise EAbort.Create('Abort it');
ShowMessage('Hello2');
except
on E: Exception do
showmessage('On Exception');
end;
執行結果顯示兩個訊息框,一個是”Hello1”,另一個是”On Exception」。這表明,EAbort確實發揮了作用,因為它跳過了」ShowMessage('Hello2')」這個語句;同時,沒有出現」Abort it」的訊息框,也證實了EAbort異常類別的不出現對話框的特點(在設計期間也是如此);並且,訊息框」On Exception」表明,雖然可能EAbort是個不同於普通異常的異數,但這並不妨礙我們沿用老的Try-Except語句來捕獲它。
2.為什麼要用EAbort ?
EAbort在某些場合下很有用。例如當我們需要終止某項操作,而又不希望讓使用者察覺(不想讓他們看到預設的異常訊息框)。當然,要達到相同的效果,使用普通的異常也可以做到(例如使用Try-Except句型,將程式碼放在Try段,需要終止操作則raise一個異常,而在Except段不寫任何程式碼),但這一切沒有比使用EAbort來的簡單直接。
3.有什麼簡單一點的嗎? ――使用Abort過程
SysUtils單元中定義的一個流程Abort可以讓我們方便的使用EAbort。查看Abort的實作源碼:
PRocedure Abort;
function ReturnAddr: Pointer;
asm
MOV EAX,[EBP + 4]
end;
begin
raise EAbort.Create(SOperationAborted) at ReturnAddr;
end;
這裡的SOperationAborted通常是」 Operation aborted」。
4.揭開面紗――實現原理
也許各位跟我一樣,對於EAbort為什麼是沉默的感到好奇。 Delphi在其內部,究竟對EAbort做了什麼手腳呢?讓我們一起來看個究竟。
開啟一個新的工程,點擊Find in Files,輸入」EAbort」關鍵字,然後選取Search in Directories單選框,並將Search Directory Options中的File Mask編輯框設定為Delphi原始碼所在的目錄名稱(例如我的是:D:Program FilesBorlandDelphi6Source),同時別忘記給Include SubDirectory打勾。最後,點選”OK”開始搜尋。
結果我們發現Delphi原始碼中與EAbort有瓜葛的達17處之多。除去Sysutils單元中兩處對EAbort的聲明以及部分註釋語句,我們發現絕大多數代碼類似於:
if ExceptObject is EAbort then
以及:
if not (E is EAbort) then
等等。
無一不是根據RTTI來對EAbort特殊對待的――原來EAbort的實作就這麼簡單!
值得關注的兩個單元是:Forms(linux版本為QForms)和AppEvnts,在前者的程式碼中我們更不難找到問題的答案。請參閱Delphi原始碼:
procedure Tapplication.HandleException(Sender: TObject);
begin
if GetCapture <> 0 then SendMessage(GetCapture, WM_CANCELMODE, 0, 0);
if ExceptObject is Exception then
begin
if not (ExceptObject is EAbort) then
if Assigned(FOnException) then
FOnException(Sender, Exception(ExceptObject))
else
ShowException(Exception(ExceptObject));
end else
SysUtils.ShowException(ExceptObject, ExceptAddr);
end;
5. Abort與Break和Exit之區別
Abort和Break和Exit有些相似,又很不一樣。 Break用來在迴圈語句中跳出一層迴圈。 Exit用來跳出目前執行的函數體(或過程體)。 Abort可以讓你跳出一層或多層程式碼段,直到有異常捕獲的程式碼將它捕獲。
6.自訂沉默的異常
與聲明一個普通異常類別的子類別相同,只需將EAbort及其子類別作為祖先類別即可:
TMyException = Class(EAbort);
TNextException = Class(EAbort);
等等。
Musicwind®@HangZhou.Zhejiang.China
2001-10-20
更多文章
[文終]