根據this site,拋出一個字符串或整數是完全可用的。我覺得這很乾淨,很容易理解。 throw "description of what happened"
而不是throw std::runtime_error("description of what happened")
有什麼缺點?C++異常:爲什麼使用或擴展std :: exception?
回答
該網站是愚蠢的,並教壞設計。
如果你丟int
或char*
,那麼你將不得不使用int
或char*
捕獲它。您可以使用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
來處理它們,如果這樣做有利於你。但要注意的一點是:那就是不是的一個要求!
簡而言之,您可以利用類層次結構。
主要是因爲當你與其他人一起工作時,你必須同意接受什麼。如果我試着抓到一個const std::exception&
,並且你扔const char*
,那麼我不會抓住你的東西,並且可能發生不好的事情。
只要每個人都堅持下去,究竟什麼類型會被拋出並被捕獲並不重要。我猜std::exception
被選爲const char*
,因爲它允許你在異常對象中放入更多的字符串。它只是更靈活。
如果你在代碼中規定只拋出從std :: exception派生的異常,那麼捕獲它們更容易。換句話說,你可以只是有一個單一的catch子句上的std ::例外:
catch (std::exception& e)
{
log_message(e);
throw;
}
但是,如果你不遵循這個規則,那麼你最終不得不寫catch子句,當你不就得了。從他其他答案
在每一層捕獲和重新拋出都沒有什麼好處,如果你真的有事要做(使用C++,使用RAII,這應該很少見)或者「吞併」它,只使用catch語句。 –
我發現它非常有用,可用於爲不期望的異常生成堆棧跟蹤。它有助於診斷錯誤並跟蹤異常來自哪裏。 – sashang
我同意棧很有用,但是你的方法有兩個缺點。首先,它會使代碼混亂,當發生異常時要採取*特定*操作時,不再明顯。其次,這是一個性能問題,因爲受gcc或Clang等流行編譯器使用的零成本例外實施會對投擲造成嚴厲的懲罰。還有其他的,我找到更好的選擇。在投擲點捕捉堆棧的平臺特定代碼是一個;另一種方法是使用RAII記錄在放卷期間添加到例外的「筆記」。 –
一個額外的觀點是這樣的 -
如果拋出int或字符串,你想趕上一個特定的錯誤你不能。 你必須捕獲所有「int」異常,然後比較你想要捕捉的異常,然後重新引發任何你沒有準備處理的異常。如果你從異常繼承,你可以捕獲你想要處理的特定異常,並且仍然有優勢,如果你想處理它們,你可以捕獲std :: exception。
- 1. C++異常; int或std :: exception?
- 2. 爲什麼擴展Exception類?
- 3. 爲什麼Exception(str())拋出異常?
- 4. 什麼是c中的ruby異常類對象的擴展?
- 5. 爲什麼java ArrayIndexOutOfBound異常擴展IndexOutofBound異常不是可拋出的?
- 6. 爲什麼異常在類名中通常有後綴'Exception'?
- 7. C++通過繼承std :: exception創建新的異常
- 8. 擴展DroidGap異常
- 9. C#中的Specific和Exception異常有什麼區別?
- 10. 爲什麼我的ObservableCollection擴展會導致運行時異常?
- 11. 爲什麼spring-data-commons中的異常不會擴展DataAccessException?
- 12. 爲什麼要在DAO中擴展異常?
- 13. C++異常:std :: bad_alloc
- 14. Symfony2擴展異常類
- 15. Haskell可擴展IO異常?
- 16. 爲什麼使用repmat()擴展數組?
- 17. 爲什麼要使用擴展方法?
- 18. C++ 11:將std :: is_pointer擴展到std :: shared_ptr
- 19. C++,爲什麼使用const std :: string&parameterName?
- 20. 的Android APK擴展異常
- 21. 創建從std :: exception派生的用戶異常?
- 22. 使用Axis2 wsdl2java生成的異常類不會擴展異常
- 23. 運行時異常從異常擴展並且自定義異常從異常延伸爲什麼後者是編譯時異常而其他不是?
- 24. 什麼是hsfiles?爲什麼使用「.hsfiles」擴展名而不是常規的「.hs」?
- 25. 爲什麼C++ CLI不允許使用擴展方法?
- 26. window.postMessage行爲異常的Chrome擴展
- 27. 爲什麼「Exception Exception」不能捕獲SystemExit?
- 28. 擴展std :: list
- 29. ANSI C有哪些最常用的擴展(或使用)?
- 30. 爲什麼android應用程序擴展名爲.apk?爲什麼不.jar或.jad?
所以基本上它允許繼承來簡化錯誤處理的設計。非常優雅。如果我定義自己的異常類,並且這樣做,我可以產生相同的結果,是的? –
@StevenLu如果你派生自己的異常類,那麼你重新發明輪子,並有可能破壞取決於捕獲std :: exception的代碼。雖然這可能適用於您的個人項目,但它使您的代碼很難分發給其他人。標準的方法是具有一個特定於應用程序的異常層次結構,該異常層次結構將'std :: exception'子類化。例如,讓所有異常都是'StevenLuException'的子類,它是'std :: exception'的子類。 – sfstewman
@StevenLu:如果你的異常類最終來自'std :: exception',那麼是的,這是一個優雅的設計。在我的示例代碼中查看名爲'your_own_defined_exception'的* third *異常。我說它最終必須從'std :: exception'派生。 – Nawaz