?? 029.htm
字號:
<HTML><HEAD><meta http-equiv="Content-Type" content="text/html; charset=GB2312"><TITLE>-->DELPHI基礎教程-->第十二章 異常處理與程序調試(二)</TITLE>
<META NAME="keywords" CONTENT=" DELPHI基礎教程 第十二章 異常處理與程序調試(二)">
<META NAME="description" CONTENT=" - DELPHI基礎教程 - 第十二章 異常處理與程序調試(二)">
<style>
<!--
#page {position:absolute; z-index:0; left:0px; top:0px}
.tt3 {font: 9pt/12pt "宋體"}
.tt2 {font: 12pt/15pt "宋體"}
a {text-decoration:none}
a:hover {color: blue;text-decoration:underline}
-->
</style>
</HEAD>
<body text="#000000" aLink=#9900ff link=#006699 vLink=#006699 bgcolor="#FFFFFF" leftmargin="3" topmargin="3" marginheight="3" marginwidth="3">
<TABLE WIDTH="100%" CELLPADDING=10 CELLSPACING=0 BORDER=0>
<TR>
<TD CLASS="tt3" VALIGN="top" width="8%" bgcolor="#e0e0e0"><strong><A HREF="030.htm"><FONT style="FONT-SIZE: 9pt">后一頁</font></A><BR>
<A HREF="028.htm"><FONT style="FONT-SIZE: 9pt">前一頁</font></A><BR>
<A HREF="index.html"><FONT style="FONT-SIZE: 9pt">回目錄</font></A><BR>
<A HREF="../../../../index.htm"><FONT style="FONT-SIZE: 9pt">回首頁</font></A><BR>
</strong>
</TD>
<TD class="tt2" bgcolor="#F5F8F8" width="84%"><center><B><FONT style="FONT-SIZE: 16.5pt" COLOR="#FF6666" FACE="楷體_GB2312">第十二章 異常處理與程序調試(二)</FONT></B></center>
<hr color="#EE9B73" size="1" width="94%">
</font><p align="center">12.3<font face="宋體" lang="ZH-CN"> 異常響應 </p>
<p> </font> <font face="宋體" lang="ZH-CN">異常響應為開發者提供了一個按自己的需要進行異常處理的機制。</font>try
<font face="宋體" lang="ZH-CN">…</font>except <font face="宋體" lang="ZH-CN">…</font>end<font
face="宋體" lang="ZH-CN">形成了一個異常響應保護塊。與</font>finally<font
face="宋體" lang="ZH-CN">不同的是:正常情況下</font>except <font face="宋體"
lang="ZH-CN">后面的語句并不被執行,而當異常發生時程序自動跳到</font>except<font
face="宋體" lang="ZH-CN">,進入異常響應處理模塊。當異常被響應后異常類自動清除。</p>
<p> 下面的例子表示了文件打開、刪除過程中發生異常時的處理情況: </p>
</font><p>uses Dialogs;</p>
<p>var</p>
<p>F: Textfile;</p>
<p>begin</p>
<p>OpenDialog1.Title := 'Delete File';</p>
<p>if OpenDialog1.Execute then</p>
<p>begin</p>
<p>AssignFile(F, OpenDialog1.FileName);</p>
<p>try</p>
<p>Reset(F);</p>
<p>if MessageDlg('Erase ' +OpenDialog1.FileName + '?',</p>
<p>mtConfirmation, [mbYes, mbNo], 0) = mrYes then</p>
<p>begin</p>
<p>System.CloseFile(F);</p>
<p>Erase(F);</p>
<p>end;</p>
<p>except</p>
<p>on EInOutError do</p>
<p>MessageDlg('File I/O error.', mtError, [mbOk], 0);</p>
<p>on EAccessDenied do</p>
<p>MessageDlg('File access denied.', mtError, [mbOk], 0);</p>
<p>end;</p>
<p>end;</p>
<p>end.</p>
<font face="宋體" lang="ZH-CN"><p> 保留字</font>on<font face="宋體"
lang="ZH-CN">…</font>do<font face="宋體" lang="ZH-CN">用于判斷異常類型。必須注意的是:</font>except<font
face="宋體" lang="ZH-CN">后面的語句必須包含在某一個</font>on<font
face="宋體" lang="ZH-CN">…</font>do<font face="宋體" lang="ZH-CN">模塊中,而不能單獨存在。這又是同</font>finally<font
face="宋體" lang="ZH-CN">不同的一個地方。 </p>
</font><p>12.3.1 <font face="宋體" lang="ZH-CN">使用異常實例 </p>
<p> 上面所使用的異常響應方法可總結為如下的形式: </p>
<p> </font>on ExceptionType do</p>
<p>{<font face="宋體" lang="ZH-CN">響應某一類的異常} </p>
<p> 這種方法唯一使用的信息是異常的類型。一般情況下這已能滿足我們的需要。但我們卻無法獲取異常實例中包含的信息,比如異常消息、錯誤代碼等。假設我們需要對它們進行處理,那么就必須使用異常實例。</p>
<p> 為了使用異常實例,需要為特定響應模塊提供一個臨時變量來保存它: </p>
<p> </font>on EInstance : ExceptionType do<font face="宋體" lang="ZH-CN"> … </font></p>
<font face="宋體" lang="ZH-CN"><p> 在當前響應模塊中我們可以象使用一個普通對象那樣來引用它的數據成員。但在當前響應模塊之外不被承認。</p>
<p> 下面的代碼用于獲取異常消息并按自己的方式顯示它: </p>
<p>{窗口中包括一個</font>ScrollBar<font face="宋體" lang="ZH-CN">部件,一個</font>Button<font
face="宋體" lang="ZH-CN">部件} </p>
</font><p>procedure TErrorForm.Button1Click(Sender: TObject);</p>
<p>begin</p>
<p>try</p>
<p>ScrollBar1.Max := ScrollBar1.Min-1;</p>
<p>except</p>
<p>on E: EInvalidOperation do</p>
<p>MessageDlg('Ignoring Exception:'+E.Message,</p>
<p>mtInformation,[mbOK],0);</p>
<p>end;</p>
<p>end; </p>
<p>12.3.2 <font face="宋體" lang="ZH-CN">提供缺省響應 </p>
<p> 在異常響應模塊中,一般我們只對希望響應的特定異常進行處理。如果一個異常發生而響應模塊并沒有包含對它的處理代碼,則退出當前響應模塊,異常類仍被保留。</p>
<p> 為了保證任何異常發生后都能在當前響應模塊中被清除,可以定義缺省響應: </p>
</font><p>try</p>
<p>{<font face="宋體" lang="ZH-CN">程序正常功能}</font></p>
<p>except</p>
<p>on ESomething do</p>
<p>{<font face="宋體" lang="ZH-CN">響應特定異常}</font></p>
<p>else</p>
<p>{<font face="宋體" lang="ZH-CN">提供缺省響應}</font></p>
<p>end; </p>
<p><font face="宋體" lang="ZH-CN">由于</font>else<font face="宋體" lang="ZH-CN">可以響應任何異常,包括我們一無所知的異常,因此在缺省響應中最好只包括諸如顯示一個消息框之類的處理,而不要改變程序的運行狀態或數據。 </p>
</font><p>12.3.3 <font face="宋體" lang="ZH-CN">響應一族異常 </p>
<p> 諸如</p>
</font><p><font face="宋體" lang="ZH-CN"> on ExceptionType do</font></p>
<font face="宋體" lang="ZH-CN"><p>的異常響應語句不僅可響應本類異常,而且可以響應子類異常。對于象</font>EIntError<font
face="宋體" lang="ZH-CN">、</font>EMathError<font face="宋體" lang="ZH-CN">等系統不會引發的異常,它們將只響應其子類異常。而對于象</p>
<p> </font>on Exception do</p>
<font face="宋體" lang="ZH-CN"><p>這樣的語句將會對任何異常進行響應。</p>
<p> 下面一段代碼對整數越界異常進行單獨處理,而對其它整數異常進行統一處理: </p>
<p> </font>try</p>
<p>{<font face="宋體" lang="ZH-CN">整數運算}</font></p>
<p>except</p>
<p>on ERangeError do</p>
<p>{<font face="宋體" lang="ZH-CN">越界處理}</font></p>
<p>on EIntError do</p>
<p>{<font face="宋體" lang="ZH-CN">其它整數異常處理}</font></p>
<p>end;<font face="宋體" lang="ZH-CN"> </font></p>
<p><font face="宋體" lang="ZH-CN">由于異常在處理后即被清除,因而上面的代碼可保證不會使</font>ERangeError<font
face="宋體" lang="ZH-CN">異常被多次處理。假如顛倒兩條響應語句的順序,則</font>ERangeError<font
face="宋體" lang="ZH-CN">異常響應將永遠沒有被執行的機會。 </p>
<p> 由于異常在處理后即被清除,因而當希望對異常進行多次處理時就需要使用保留字</font>raise<font
face="宋體" lang="ZH-CN">來重引發一個當前異常。</p>
<p> 下面的代碼同時使用了異常響應和異常保護。異常響應用于設置變量的值,異常保護用于釋放資源。當異常響應結束時利用</font>raise<font
face="宋體" lang="ZH-CN">重引發一個當前異常。 </p>
</font><p>var</p>
<p>APointer: Pointer ;</p>
<p>AInt , ADiv: Integer;</p>
<p>begin</p>
<p>ADiv := 0;</p>
<p>GetMem ( APointer , 1024 );</p>
<p>try</p>
<p>try</p>
<p>AInt := 10 div ADiv ;</p>
<p>except</p>
<p>on EDivByZero do</p>
<p>begin</p>
<p>AInt := 0 ;</p>
<p>raise;</p>
<p>end;</p>
<p>end; </p>
<p>finally</p>
<p>FreeMem ( APointer , 1024 );</p>
<p>end;</p>
<p>end;</p>
<font face="宋體" lang="ZH-CN"><p> 上面一段代碼體現了異常處理的嵌套。異常保護、異常響應可以單獨嵌套也可以如上例所示的那樣相互嵌套。 </p>
</font><p>12.3.5 <font face="宋體" lang="ZH-CN">自定義異常類的應用 </p>
<p> 利用</font>Delphi<font face="宋體" lang="ZH-CN">的異常類機制我們可以定義自己的異常類來處理程序執行中的異常情況。同標準異常不同的是:這種異常情況并不是相對于系統的正常運行,而是應用程序的預設定狀態。比如輸入一個非法的口令、輸入數據值超出設定范圍、計算結果偏離預計值等等。</p>
<p> 使用自定義異常需要:</p>
<p> </font>1.<font face="宋體" lang="ZH-CN">自己定義一個異常對象類;</p>
<p> </font>2.<font face="宋體" lang="ZH-CN">自己引發一個異常。 </p>
</font><p>12.3.5.1 <font face="宋體" lang="ZH-CN">定義異常對象類 </p>
<p> 異常是對象,所以定義一類新的異常同定義一個新的對象類型并無太大區別。由于缺省異常處理只處理從</font>Exception<font
face="宋體" lang="ZH-CN">或</font>Exception<font face="宋體" lang="ZH-CN">子類繼承的對象,因而自定義異常類應該作為</font>Exception<font
face="宋體" lang="ZH-CN">或其它標準異常類的子類。這樣,假如在一個模塊中引發了一個新定義的異常,而這個模塊并沒有包含對應的異常響應,則缺省異常處理機制將響應該異常,顯示一個包含異常類名稱和錯誤信息的消息框。</p>
<p> 下面是一個異常類的定義: </p>
<p> </font>type</p>
<p>EMyException = Class(Exception) ;<font face="宋體" lang="ZH-CN"> </font></p>
<p>12.3.5.2 <font face="宋體" lang="ZH-CN">自引發異常 </p>
<p> 引發一個異常,調用保留字</font>raise<font face="宋體" lang="ZH-CN">,后邊跟一個異常類的實例。</p>
<p> 假如定義: </p>
</font><p>type</p>
<p>EPasswordInvalid = Class(Exception); </p>
<p><font face="宋體" lang="ZH-CN">則在程序中如下的語句將引發一個</font>EPasswordInvalid<font
face="宋體" lang="ZH-CN">異常: </p>
</font><p><font face="宋體" lang="ZH-CN"> </font>If Password <> CorrectPassword
then</p>
<p>raise EPasswordInvalid.Create('Incorrect Password entered');</p>
<font face="宋體" lang="ZH-CN"><p> 異常產生時把</font>System<font
face="宋體" lang="ZH-CN">庫單元中定義的變量</font>ErrorAddr<font face="宋體"
lang="ZH-CN">的值置為應用程序產生異常處的地址。在你的異常處理過程中可以引用</font>ErrorAddr<font
face="宋體" lang="ZH-CN">的值。</p>
<p> 在自己引發一個異常時,同樣可以為</font>ErrorAddr<font
face="宋體" lang="ZH-CN">分配一個值。</p>
<p> 為異常分配一個錯誤地址需要使用保留字</font>at<font
face="宋體" lang="ZH-CN">,使用格式如下: </p>
<p> </font>raise EInstance at Address_Expession; </p>
<p>12.3.5.3 <font face="宋體" lang="ZH-CN">自定義異常的應用舉例 </p>
<p>下面我們給出一個利用自定義異常編程的完整實例。</font></p>
<p><font face="宋體" lang="ZH-CN">兩個標簽框</font>(Label1<font face="宋體"
lang="ZH-CN">、</font>Label2)<font face="宋體" lang="ZH-CN">標示對應編輯框的功能。編輯框</font>PassWord<font
face="宋體" lang="ZH-CN">和</font>InputEdit<font face="宋體" lang="ZH-CN">用于輸入口令和數字。程序啟動時</font>Label2<font
face="宋體" lang="ZH-CN">、</font>InputEdit<font face="宋體" lang="ZH-CN">不可見。當在</font>PassWord<font
face="宋體" lang="ZH-CN">中輸入正確的口令時,</font>Label2<font face="宋體"
lang="ZH-CN">、</font>InputBox<font face="宋體" lang="ZH-CN">出現在屏幕上。此時</font>Label1<font
face="宋體" lang="ZH-CN">、</font>PassWord<font face="宋體" lang="ZH-CN">隱藏。</font></p>
<p><font face="宋體" lang="ZH-CN">設計時,令</font>Label2<font face="宋體"
lang="ZH-CN">、</font>InputEdit<font face="宋體" lang="ZH-CN">的</font>Visible<font
face="宋體" lang="ZH-CN">屬性為</font>False<font face="宋體" lang="ZH-CN">。通過設置</font>PassWord<font
face="宋體" lang="ZH-CN">的</font>PassWordChar<font face="宋體" lang="ZH-CN">可以確定輸入口令時回顯在屏幕上的字符。</font></p>
<p><font face="宋體" lang="ZH-CN">自定義異常</font>EInvalidPassWord<font
face="宋體" lang="ZH-CN">和</font>EInvalidInput<font face="宋體" lang="ZH-CN">分別用于表示輸入的口令非法和數字非法。它們都是自定義異常</font>EInValidation<font
face="宋體" lang="ZH-CN">的子類。而</font>EInValidation<font face="宋體"
lang="ZH-CN">直接從</font>Exception<font face="宋體" lang="ZH-CN">異常類派生。</font></p>
<p><font face="宋體" lang="ZH-CN">下面是三個異常類的定義。 </p>
</font><p>type</p>
<p>EInValidation = class(Exception)</p>
<p>public</p>
<p>ErrorCode: Integer;</p>
<p>constructor Create(Const Msg: String;ErrorNum: Integer);</p>
<p>end;</p>
<p>EInvalidPassWord = class(EInValidation)</p>
<p>public</p>
<p>constructor Create;</p>
<p>end;</p>
<p>EInvalidInput = class(EInValidation)</p>
<p>public</p>
<p>constructor Create(ErrorNum: Integer);</p>
<p>end; </p>
<p>EInValidation<font face="宋體" lang="ZH-CN">增加了一個公有成員</font>ErrorCode<font
face="宋體" lang="ZH-CN">來保存錯誤代碼。錯誤代碼的增加提供了很大的編程靈活性。對于異常類,可以根據錯誤代碼提供不同的錯誤信息;對于使用者可以通過截取錯誤代碼,在</font>try...except<font
face="宋體" lang="ZH-CN">模塊之外來處理異常。</font></p>
<p><font face="宋體" lang="ZH-CN">從以上定義可以發現:</font>EInvalidPassWord<font
face="宋體" lang="ZH-CN">和</font>EInvalidInput<font face="宋體" lang="ZH-CN">的構造函數參數表中沒有表示錯誤信息的參數。事實上,它們保存在構造函數內部。下面是三個自定義異常類構造函數的實現代碼。 </p>
</font><p>constructor EInValidation.Create(Const Msg: String; ErrorNum: Integer);</p>
<p>begin</p>
<p>inherited Create(Msg);</p>
<p>ErrorCode := ErrorNum;</p>
<p>end;</p>
<p>constructor EInValidPassWord.Create;</p>
<p>begin</p>
<p>inherited Create('Invalid Password Entered',0);</p>
<p>end;</p>
<p>constructor EInValidInput.Create(ErrorNum: Integer);</p>
<p>var</p>
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -