C++、Java和C#中的異常處理

 

C++中異常:
1、可以拋出任何異常。雖然標準C++定義了std::exception類,但throw的對象可以是任何對象。包括int、char*等。例如:

throw 100;

try {
 
// do something 
}
 catch (int num) {
 
// do something 
}

但是,C++標準庫中拋出的所有異常,都是派生自std::exception類。
std::exception定義如下:

class exception {
    
public:
        exception( );
        exception(
const char *const&);
        exception(
const char *const&int);
        exception(
const exception&);
        exception
& operator=(const exception&);
        
virtual ~exception( );
        
virtual const char *what( ) const;
}
;


2、標準C++中,是沒有finally子句。熟悉Java和C#的朋友,也許會覺得奇怪!沒有finally子句,使用的確不方便。

3、C++中,函數的聲明,缺省時可以拋出任何異常的,也可以使用異常規範來約束函數拋出的異常,如:

//可以拋出任何異常
void f() {
 
throw 100;
}


//描述該函數不會拋出任何異常
void f() throw() {
}


//描述該函數會拋出int或者char*類型的異常
void f() throw(intchar*{
    
// do something 
}

但是,C++中的異常規範不是很可靠。如下的代碼也是可以編譯通過的,但是編譯器會給出警告。

void f() throw(intchar*{
    
throw "100";
}


4、C++的異常可以派生自多個異常基類。這一個特性使得難以分類的異常容易處理,例如網絡文件的異常:

class file_exception {}
class network_exception {}
class newwork_file_exception : public file_exception, public network_exception {}


5、捕捉所有異常的語法。C++中,不是單根繼承的,所以你不能,如同Java或者C#那樣,通過捕捉某個基類來捕捉所有的異常。

try {
 
// do something 
}
 catch (//捕捉所有的異常
 
// do something 
}

總結,C++中,命名空間和異常規範是作爲針對大規模程序設計而引入的特性。但是由於C++中沒有垃圾收集機制,異常造成了資源管理變得非常複雜。在C++中,編寫異常安全的代碼,是十分困難的。



Java中的異常:

1、可以拋出任何派生自了Throwable的類。Throwable類的定義如下:

public class Throwable implements Serializable {
 
public Throwable();
 
public Throwable(String message);
 
public Throwable(String message, Throwable cause); //@since  1.4
 public Throwable(Throwable cause); //@since  1.4
 public String getMessage();
 
public String getLocalizedMessage(); //@since   JDK1.1
 public Throwable getCause(); //@since 1.4
 public synchronized Throwable initCause(Throwable cause); //@since  1.4
 public String toString();
 
public void printStackTrace();
 
public void printStackTrace(PrintStream s);
 
public void printStackTrace(PrintWriter s); //@since   JDK1.1
 private void printStackTraceAsCause(PrintWriter s,
                                        StackTraceElement[] causedTrace);
 
public synchronized native Throwable fillInStackTrace(); 
  
public StackTraceElement[] getStackTrace(); //@since  1.4
  public void setStackTrace(StackTraceElement[] stackTrace); //@since  1.4
}

Throwable下分Exception和Error。

public class Exception extends Throwable {}
public class Error extends Throwable {}

而Exception中,有一個特別的派生類,RuntimeException,如下:
public class RuntimeException extends Exception {}
類圖如下:



2、Java中,也使用異常規範,並且在整個基礎類庫中都使用。Java是基於JVM運行,但是JVM本身就拋出異常,也就是,所有的方法都可能拋出異常。因此,Java編譯器編譯不檢查Error和RuntimeException。與C++不同,沒有異常規範,缺省不允許拋出任何非RuntimeException和Error的異常。如下:

public void f() {
 
throw new RuntimeException(); //正確
}


public void f() {
 
throw new Error(); //正確
}

以下的代碼編譯出錯

public void f() {
 
throw new Exception(); 
}

使用異常規範的正確例子:

public WfException extends Exception {}

public void f() throws WfException {
 
throw new WfException();
}


3、Throwable、Exception、RuntimeException中部分成員,是在不同的JDK版本中添加的,編寫代碼的時候需要注意。如下的代碼不能在JDK 1.3中編譯通過:

public void f() throws WfException {
 
try {
  
// do something 
 }
 catch (Exception e) {
  
throw new WfException ("", e);
 }

}


4、Java中的try語法,包括finally子句。如下:

try {
 
// do something 
}
 catch (Exception e) {
 
// do something 
}
 finally {
 
// do something 
}

 

C#中的異常:
1、C#異常的侷限性。C#是基於CLR運行的,由於CLR需要支持多種語言,其異常的實現受到了較大的侷限。一個重要的特徵就是沒有異常規範,很多人對此很失望!Anders Hejlsberg曾專門發表過文章,說明爲什麼C#不支持異常規範,說得也很有道理。但是,沒有異常規範的C#,變得簡單,但也更容易犯錯誤,在這一點上,我更喜歡Java,而不喜歡C#的方式。沒有異常規範,編譯器就不會幫我們檢查代碼,是否做了try ... catch處理。

2、異常的結構。在.NET Framework中,所有的異常派生自System.Exception基類。其下有兩個子類:SystemException和ApplicationException。自行編寫異常類,不建議直接派生自Exception類,而是應該派生自ApplicationException。

3、C#猶如Java,也支持finally的寫法。如:

try 
{
 
// do something 
}
 
catch (Exception e) 
{
 
// do something 
}
 
finally 
{
 
// do something 
}

posted on 2004-07-19 21:06 溫少 閱讀(1414) 評論(4)  編輯  收藏 所屬分類: .NETJava推薦閱讀

發佈了44 篇原創文章 · 獲贊 0 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章