更新歷史:No.2
更新時間:2001-10-21 02:42
更新人員:Musicwind®
更新備注:修改格式。
更新歷史:No.1
更新時間:2001-10-19 21:15
更新人員:Musicwind®
更新備注:創(chuàng)建。
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
前言:沉浸于Delphi已逾三載,可是每每翻閱Delphi的幫助文檔,還是會有許多收獲,于是不免感慨Delphi的博大!在慚愧之余,將些許心得和收獲整理,與諸位當(dāng)中如我般自大而學(xué)識尚淺者,共勉。
1. 什么是沉默的異常?(為什么不是沉默的羔羊?;-))
沉默的異常,即Slient Exceptions,指的是在缺省情況下不會出現(xiàn)討厭的消息提示框的異常類型:EAbort。在Object Pascal中,異常類EAbort是所有沉默的異常類的祖先類(而EAbort是繼承Exception而來)。引發(fā)(Raise)一個EAbort將導(dǎo)致一個執(zhí)行模塊的停止,直到有最外層的異常處理模塊截獲它,但是并不因此出現(xiàn)帶有紅色停止標(biāo)志的消息框。參考如下代碼:
try
ShowMessage('Hello1');
Raise EAbort.Create('Abort it');
ShowMessage('Hello2');
except
on E: Exception do
showmessage('On Exception');
end;
執(zhí)行結(jié)果顯示兩個消息框,一個是”Hello1”,另一個是”O(jiān)n Exception”。這表明,EAbort確實發(fā)揮了作用,因為它跳過了”ShowMessage(‘Hello2’)”這個語句;同時,沒有出現(xiàn)”Abort it”的消息框,也證實了EAbort異常類的不出現(xiàn)對話框的特點(在設(shè)計期間也是如此);并且,消息框”O(jiān)n Exception”表明,雖然可能EAbort是個不同于普通異常的異數(shù),但這并不妨礙我們沿用老的Try-Except語句來捕獲它。
2. 為什么要用EAbort?
EAbort在某些場合下很有用。比如當(dāng)我們需要終止某項操作,而又不希望讓用戶察覺(不想讓他們看到默認(rèn)的異常消息框)。當(dāng)然,要達(dá)到相同的效果,使用普通的異常也可以做到(比如使用Try-Except句型,將代碼放在Try段,需要終止操作則raise一個異常,而在Except段不寫任何代碼),但是這一切沒有比使用EAbort來的簡單又直接。
3. 有什么簡便一點的嗎?――使用Abort過程
SysUtils單元中定義的一個過程Abort可以讓我們方便的使用EAbort。查看Abort的實現(xiàn)源碼:
PRocedure Abort;
function ReturnAddr: Pointer;
asm
MOV EAX,[EBP + 4]
end;
begin
raise EAbort.Create(SOperationAborted) at ReturnAddr;
end;
這里的SOperationAborted通常就是” Operation aborted”。
4. 揭開面紗――實現(xiàn)原理
也許各位和我一樣,對于EAbort為什么是沉默的感到好奇。Delphi在其內(nèi)部,究竟對EAbort做了什么手腳呢?讓我們一起來看個究竟。
打開一個新的工程,點擊Find in Files,輸入”EAbort”關(guān)鍵字,然后選中Search in Directories單選框,并將Search Directory Options中的File Mask編輯框設(shè)置為Delphi源碼所在的目錄名(比如我的是:D:Program FilesBorlandDelphi6Source),同時別忘記給Include SubDirectory打勾。最后,點擊”O(jiān)K”開始搜索。
結(jié)果我們發(fā)現(xiàn)Delphi源碼中與EAbort有瓜葛的達(dá)17處之多。除去Sysutils單元中兩處對EAbort的聲明以及部分注釋語句,我們發(fā)現(xiàn)絕大多數(shù)代碼類似于:
if ExceptObject is EAbort then
以及:
if not (E is EAbort) then
等等。
無一不是根據(jù)RTTI來對EAbort特殊對待的――原來EAbort的實現(xiàn)就這么簡單!
值得關(guān)注的兩個單元是: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之區(qū)別
Abort和Break和Exit有些相似,又很不同。Break用來在循環(huán)語句中跳出一層循環(huán)。Exit用來跳出當(dāng)前執(zhí)行的函數(shù)體(或過程體)。Abort可以讓你跳出一層或者多層代碼段,直到有異常捕獲的代碼將它捕獲。
6. 自定義沉默的異常
與聲明一個普通異常類的子類相同,只需將EAbort及其子類作為祖先類即可:
TMyException = Class(EAbort);
TNextException = Class(EAbort);
等等。
Musicwind®@HangZhou.Zhejiang.China
2001-10-20
[文終]
新聞熱點
疑難解答
圖片精選