tft每日頭條

 > 生活

 > delphi基礎教程第三講

delphi基礎教程第三講

生活 更新时间:2024-09-28 09:59:09

delphi基礎教程第三講(Delphi基礎教程圖文版之異常機制)1

每一段程序都有可能出錯!這是軟件業的一個不容置疑的現象和規律。事實上,傳統的 if…else…結構完全可以解決所有的錯誤,那麼,為什麼還需要異常機制

答案很簡單:異常提供了一種更加靈活和開放的方式,使得後來的編程者可以來根據實際的情況處理這種錯誤,而不是使用預先設定好的處理結果。實際上,這就是異常處理機制的核心

使用場景

異常信息的處理方法(寫日志、抛出異常),函數或過程出現異常時,隻能抛出異常,禁止彈出對話框架。

函數及過程、控件中發生異常,通常是直接抛出異常,不要顯示信息提示框;

界面操作(按鈕)中的異常,可以顯示提示信息(視具體應用而定),也可以不顯示提示而将異常信息保存到日志文件或兩種方式同時使用;

DLL文件中的異常:如果是函數或過程,發生異常時就直接抛出異常;如果是界面操作,則按界面操作(按鈕)中的異常處理方法處理。

設計期異常

這種異常類型發生在設計期,通常是因為給組件的某個屬性輸入了非法的值。例如,在設計數據庫應用程序時指定了一個沒有定義的數據庫别名。

這種類型的異常比較容易被發現和糾正,因為Delphi能夠對屬性的值進行合法性檢查。一旦發現這種錯誤,Delphi将彈出一個警告窗口,提示你糾正錯誤。

編譯期異常

編譯期異常也叫語法錯誤,當程序代碼違反了Object Pascal的語法規則時将發生這種錯誤。換一種更為直白的說法就是代碼寫錯了

如果程序代碼中有語法錯誤,編譯就不能通過,代碼編輯器的狀态欄将給出錯誤信息提示,并在代碼編輯器中突出顯示有語法錯誤的行。

比較常見的語法錯誤是數據類型不匹配,特别是調用RTL、VCL或Windows的API時容易發生參數不匹配的錯誤。

運行期異常

程序雖然通過了編譯,但在運行時失敗了,這種錯誤稱為運行期異常

這種異常類型通常情況下不容易被肉眼看出來,例如,程序試圖打開一個不存在的文件,在運算時出現了被零除、使用一個空對象調用了該類的成員。

相關語法

Delphi中異常的基類是System.SysUtils.Exception,換句話說就是所有的異常類都是Exception的子類。參考Delphi這種異常分類處理方式,我們也可以從Exception派生一個自定義的異常類

有人可能覺得沒有自己定義異常類的必要,其實不然,就算Delphi定義的類型夠多它也無法囊括所有的異常類型,而針對一些特定的場景則需要我們自己定義異常類

raise

在講如何處理異常之前我們需要先了解異常是如何産生的,很簡單異常的處理過程就類似一個推卸責任的過程。。。

raise這個關鍵字的主要作用是抛出一個攜帶異常信息的對象,而這個對象所對應的類必須是Exception或者其子類,如果在抛的過程中沒有遇到處理異常的程序會一直到系統為止,具體的語法如下

raise Exception.Create('我抛出的異常!');

try…except…end

在try 體内的代碼發生異常時,系統将轉向except 部分進行異常的處理。這是Delphi處理異常的最基本的方式之一。

隻有當try 體内的代碼發生異常時,才會跳轉到except 裡面的代碼進行執行

需要注意的是在excpt...end之間的代碼依然有可能存在異常

try…finally…end

這種異常處理結構一般用于保護windows的資源分配等方面,它确保了無論try 體内的代碼是否發生異常,都需要由系統進行最後的統一處理的一些Windows對象的正确處理。和try…except…end不同,該結構的finally部分總被執行

需要注意的是:不存在try…except…finally…end 結構 。其實我個人而言更喜歡這種結構,但是在Delphi中不存在這種結構

自定義一個異常

根據前面提到的規則,定義一個異常就是定義一個Exception類的派生類,所以我們可以得到下面的代碼

type TArithmeticException = class(Exception) public constructor Create(Msg: string); overload; end; constructor TArithmeticException.Create(Msg: string); begin inherited Create(Msg); end;

當然,基類可以是Exception或者是Exception的任何一個任何層次的派生類

其實構造方法可以不進行重寫,但是為了代碼更為規範和較高的可讀性建議還是寫上比較好

抛出異常

根據不同的情況抛出異常是使用異常的最基本的模式。我的理解可能不是特别準确,所謂的抛出異常其實就是聲明一個異常對象

例1

begin raise TArithmeticException.Create('抛出異常'); end;

例2

begin {此處因為本類沒有聲明這種格式的函數,所以默認引用的是父類的構造函數} raise TArithmeticException.CreateFmt('%s %d', ['錯誤代碼:', 999]); end;

例3

var exc: Exception; begin {這種方式和例1沒有區别,僅僅是多了一個變量的聲明} exc := TArithmeticException.Create('發現異常'); raise exc; end;

異常類型的精确處理

可以使用 on E:異常類 do... 結構可以在 do 體内處理特定異常類所抛出的異常。

如果在except中使用 on E: 異常類 do… 的話,在except中的 on E: 異常類 do…之外不能有任何語句,例如下面的語法是正确的

try ... except on E: Exception do begin ShowMessage('OK'); ShowMessage('OK Again'); end; end;

但是下面的方式就錯了

try ... except on E: Exception do begin ShowMessage('OK'); end; //如果在except中使用 on E: 異常類 do 的話,在except中的 on E: 異常類 do之外不能有任何語句 ShowMessage('Not OK'); end;

整個的異常處理代碼

procedure Demo1(); begin raise TArithmeticException.Create('算術異常'); end; begin try try Demo1(); except on E: TArithmeticException do begin {Message即為我們前面創建對象時賦值的内容} Writeln(E.UnitName,E.ClassName, e.Message); end; on E: Exception do begin Writeln('未知異常'); end; end; finally // 此處作為資源釋放的代碼 end; end.

通過最後的代碼可以發現,我們對于代碼異常情況的處理更為詳細,一旦程序出錯更便于我們進行定位。

,

更多精彩资讯请关注tft每日頭條,我们将持续为您更新最新资讯!

查看全部

相关生活资讯推荐

热门生活资讯推荐

网友关注

Copyright 2023-2024 - www.tftnews.com All Rights Reserved