2012-04-21 52 views
5

我使用QT 4.8(C++),用於桌面應用程序的項目,並編寫異常處理是如下:如何避免在catch塊中寫入重複的代碼?

void callerMethod() 
{ 
    try 
    { 
    method1(); 
    } 
    catch(Exception1& e) 
    { 
    // display critcal error message 
    // abort application 
    } 
    catch(std::Exception& e) 
    { 
    // print exception error message 
    } 
    catch(...) 
    { 
    // print unknown exception message 
    } 
} 

void method1() 
{ 
    try 
    { 
    // some initializations 
    // some operations (here exceptions can occur) 
    // clean-up code (for successful operation i.e no exception occurred) 
    } 
    catch(Exception1& e) 
    { 
    // clean-up code 
    throw e; 
    } 
    catch(Exception2& e) 
    { 
    // clean-up code 
    throw e; 
    } 
    catch(Exception3& e) 
    { 
    // clean-up code 
    throw e; 
    } 
    catch(...) 
    { 
    // clean-up code 
    throw; 
    } 
} 

所以我的問題,我需要寫清理代碼在每一個catch塊 ? 有什麼辦法可以避免重複編寫代碼

注意 :: [在方法1()]我想重新拋出異常發生 我caller.So我不能趕上他們在一個catch塊, 由於然後鍵入的信息將會丟失。

+4

Try t o減少使用智能指針,容器類等所需的清理代碼的數量。理想情況下,應該沒有任何清理代碼。 – user763305 2012-04-21 06:43:59

+0

看來你想要做的只是'try {/ * may throw * /} catch(specific_exception const&e){/ * terminate * /}'。如果你不關心異常類型'Exception1','Exception2'等等,那麼*不會*捕獲它們。 – 2012-04-21 07:54:51

+1

此外,即使你通過引用來捕獲,你應該*使用'throw;'rethrow而不是'throw e;'來防止切片。 – ereOn 2012-04-21 08:25:42

回答

8

方法1可以通過兩個概念可以大大簡化:

  1. RAII。將任何清理代碼放入析構函數中,清理代碼將被集中。
  2. 使用不合格的throw,您不需要知道拋出的異常類型。

所以,method1()應該是這樣的:

void method1() 
{ 
    // some initializations of RAII objects 
    // some operations (here exceptions can occur) 
} 

如果從std::exception派生Exception1,因爲what()方法是虛擬的callerMethod第一catch子句可以刪除。

+1

+1。我想說這個。 RAII是這裏的解決方案。 – Nawaz 2012-04-21 06:47:23

+0

但我想分別在callerMethod()中處理Exception1。 如果發生Exception1,我想中止應用程序。 – EngineeredBrain 2012-04-21 06:52:12

+0

@AnwarShaikh:你仍然可以做到這一點。 RAII只解決你的清理問題。 – Nawaz 2012-04-21 06:54:50

0

如果你所有的清理代碼是完全一樣的,你可以在你抓盡一切(...)塊:

try { 
    // code 
} catch (...) { 
    // cleanup 
    throw; 
} 

如果你的代碼稍有不同,你可以隨時調用清理功能:

try { 
    // code 
} catch (exc1 ex) { 
    cleanup(args); 
    // exc1 specific 
    throw; 
} catch (exc2 ex) { 
    cleanup(args); 
    // exc2 specific 
    throw; 
} catch (...) { 
    cleanup(args); 
    throw; 
} 
+0

如果我寫單拋出(..)拋出異常然後,在調用方法我怎麼知道哪個異常發生。 因爲我想處理中止應用程序的Exception1。 – EngineeredBrain 2012-04-21 06:49:11

1

您應該儘可能低地拋出異常,並儘可能在捕獲鏈中捕獲它們。這自動導致更少的代碼重複,並集中處理錯誤。你在一個地方投擲/捕捉所有東西,這似乎有點......被迫。

我經常做這種事情(尤其是程序結束例外:

int main() 
try 
{ 
    function_calls_that_may_throw(); 
    // ... 
} 
catch(my_exception& e) 
{ 
    e.do_exception_stuff(); 
} 
catch(std::exception& e) 
{ 
    std::cout << e.what(); 
} 
catch(...) 
{ 
    std::cout << "Something bad happened.\n"; 
} 

這對於拋出異常,纔可能你不處理好或重試失敗的操作什麼的計劃

這種方法的好處在於,所有/大多數錯誤處理代碼都位於程序的頂層,並且調用鏈中的所有函數都不必擔心這一點,他們所做的只是當他們覺得喜歡時會拋出異常。