2012-07-02 52 views

回答

13

該網站是愚蠢的,並教壞設計。

如果你丟intchar*,那麼你將不得不使用intchar*捕獲它。您可以使用const進行限定。

如果您丟棄std::runtime_error,那麼您可以使用std::runtime_error const &或其基類std::exception const &來捕獲它。

那麼它有什麼好處?

好關於它的是,如果你把使用被最終從std::exception派生的類的異常,則可以被用於拋出異常寫只是ONE catch塊,其接受異常作爲std::exception const&,不論which derived class

下面是一個例子:

void f(A & a) 
{ 
    if (!check_arg(a)) 
    { 
      throw std::invalid_argument("invalid argument"); 
    } 
    else if (!check_size(a)) 
    { 
      throw std::length_error("invalid length");    
    } 

    //code 
    if(someCondition) 
    { 
      //assume your_own_defined_exception's ultimate base is std::exception 
      throw your_own_defined_exception("condition unsatisfied");       
    } 
    //... 

} 

現在最有趣的部分:

try 
{ 
     f(a); //it can throw exception of at least 3 types! 
} 
catch(std::exception const &e) //all types can be caught by just one catch! 
{ 
    //handle this case 
} 

好的是,你不需要catch塊只是因爲f()可以拋出不同類型的異常。你可能會寫多個catch來處理它們,如果這樣做有利於你。但要注意的一點是:那就是不是的一個要求!

簡而言之,您可以利用類層次結構。

+0

所以基本上它允許繼承來簡化錯誤處理的設計。非常優雅。如果我定義自己的異常類,並且這樣做,我可以產生相同的結果,是的? –

+3

@StevenLu如果你派生自己的異常類,那麼你重新發明輪子,並有可能破壞取決於捕獲std :: exception的代碼。雖然這可能適用於您的個人項目,但它使您的代碼很難分發給其他人。標準的方法是具有一個特定於應用程序的異常層次結構,該異常層次結構將'std :: exception'子類化。例如,讓所有異常都是'StevenLuException'的子類,它是'std :: exception'的子類。 – sfstewman

+0

@StevenLu:如果你的異常類最終來自'std :: exception',那麼是的,這是一個優雅的設計。在我的示例代碼中查看名爲'your_own_defined_exception'的* third *異常。我說它最終必須從'std :: exception'派生。 – Nawaz

1

主要是因爲當你與其他人一起工作時,你必須同意接受什麼。如果我試着抓到一個const std::exception&,並且你扔const char*,那麼我不會抓住你的東西,並且可能發生不好的事情。

只要每個人都堅持下去,究竟什麼類型會被拋出並被捕獲並不重要。我猜std::exception被選爲const char*,因爲它允許你在異常對象中放入更多的字符串。它只是更靈活。

2

如果你在代碼中規定只拋出從std :: exception派生的異常,那麼捕獲它們更容易。換句話說,你可以只是有一個單一的catch子句上的std ::例外:

catch (std::exception& e) 
{ 
    log_message(e); 
    throw; 
} 

但是,如果你不遵循這個規則,那麼你最終不得不寫catch子句,當你不就得了。從他其他答案

+0

在每一層捕獲和重新拋出都沒有什麼好處,如果你真的有事要做(使用C++,使用RAII,這應該很少見)或者「吞併」它,只使用catch語句。 –

+0

我發現它非常有用,可用於爲不期望的異常生成堆棧跟蹤。它有助於診斷錯誤並跟蹤異常來自哪裏。 – sashang

+0

我同意棧很有用,但是你的方法有兩個缺點。首先,它會使代碼混亂,當發生異常時要採取*特定*操作時,不再明顯。其次,這是一個性能問題,因爲受gcc或Clang等流行編譯器使用的零成本例外實施會對投擲造成嚴厲的懲罰。還有其他的,我找到更好的選擇。在投擲點捕捉堆棧的平臺特定代碼是一個;另一種方法是使用RAII記錄在放卷期間添加到例外的「筆記」。 –

1

一個額外的觀點是這樣的 -

如果拋出int或字符串,你想趕上一個特定的錯誤你不能。 你必須捕獲所有「int」異常,然後比較你想要捕捉的異常,然後重新引發任何你沒有準備處理的異常。如果你從異常繼承,你可以捕獲你想要處理的特定異常,並且仍然有優勢,如果你想處理它們,你可以捕獲std :: exception。

相關問題