C++核心準(zhǔn)則E.30:不要使用拋異常聲明
不要使用拋異常聲明
月季
E.30: Don't use exception specifications
E.20:不要使用拋異常聲明
Reason(原因)
Exception specifications make error handling brittle, impose a run-time cost, and have been removed from the C++ standard.
拋異常聲明讓錯誤處理更脆弱,強(qiáng)制產(chǎn)生運(yùn)行時成本,已經(jīng)從C++標(biāo)準(zhǔn)中被移除了。
Example(示例)
int use(int arg)
throw(X, Y)
{
// ...
auto x = f(arg);
// ...
}
If?f()?throws an exception different from?X?and?Y?the unexpected handler is invoked, which by default terminates. That's OK, but say that we have checked that this cannot happen and?f?is changed to throw a new exception?Z, we now have a crash on our hands unless we change?use()?(and re-test everything). The snag is that?f()?may be in a library we do not control and the new exception is not anything that?use()?can do anything about or is in any way interested in. We can change?use()?to pass?Z?through, but now?use()'s callers probably needs to be modified. This quickly becomes unmanageable. Alternatively, we can add a?try-catch?to?use()?to map?Z?into an acceptable exception. This too, quickly becomes unmanageable. Note that changes to the set of exceptions often happens at the lowest level of a system (e.g., because of changes to a network library or some middleware), so changes "bubble up" through long call chains. In a large code base, this could mean that nobody could update to a new version of a library until the last user was modified. If?use()?is part of a library, it may not be possible to update it because a change could affect unknown clients.
如果f()拋出了不同于X和Y的異常,就會激活意外的錯誤處理,而這個處理的默認(rèn)動作就是終止程序。那樣還好,假設(shè)我們已經(jīng)檢查過了,這種事情不會發(fā)生,這時如果f被修改為拋出一個新異常Z,系統(tǒng)馬上就會發(fā)生崩潰,除非我們修改use()(并且重新進(jìn)行完整測試)。麻煩在于f()可能處于某個我們無法控制的功能庫中,而且對于新異常use()也沒有什么可做的,或者根本就不感興趣。我可以修改use()將Z傳出,但是接下來user()的調(diào)用者可能需要跟著修改。情況很快就會失控?;蛘呶覀兛梢詾閡se()增加try-catch結(jié)構(gòu)將Z映射到一個可以接受的異常。情況很快會再次失控。注意成組修改異常經(jīng)常發(fā)生在系統(tǒng)的底層(例如由于網(wǎng)絡(luò)庫或某個中間件發(fā)生變化),因此變更會像氣泡一樣向上傳遞至整個調(diào)用鏈。在大規(guī)模代碼中,這可能意味著沒有人可以將庫更新到新版本,直到最后的調(diào)用者發(fā)生變更。如果use()是庫的一部分,它可能無法更新,因?yàn)檫@種變更不知道會影響誰。
The policy of letting exceptions propagate until they reach a function that potentially can handle it has proven itself over the years.
讓異常傳播直至一個有可能處理它的函數(shù),這樣的原則已經(jīng)證明自己很多年了。
Note(注意)
No. This would not be any better had exception specifications been statically enforced. For example, see?Stroustrup94.
沒有。堅(jiān)持推進(jìn)使用拋異常聲明一點(diǎn)好處也沒有。參見
Stroustrup. The Design and Evolution of C++ (Addison-Wesley, 1994).
Note(注意)
If no exception may be thrown, use?noexcept?or its equivalent?throw().
如果不會拋出任何異常,使用noexcept或者和它等價的throw()
Enforcement(實(shí)施建議)
Flag every exception specification.
標(biāo)記所有的拋出異常聲明。
原文鏈接
https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#e30-dont-use-exception-specifications
新書介紹
以下是本人3月份出版的新書,拜托多多關(guān)注!

本書利用Python 的標(biāo)準(zhǔn)GUI 工具包tkinter,通過可執(zhí)行的示例對23 個設(shè)計(jì)模式逐個進(jìn)行說明。這樣一方面可以使讀者了解真實(shí)的軟件開發(fā)工作中每個設(shè)計(jì)模式的運(yùn)用場景和想要解決的問題;另一方面通過對這些問題的解決過程進(jìn)行說明,讓讀者明白在編寫代碼時如何判斷使用設(shè)計(jì)模式的利弊,并合理運(yùn)用設(shè)計(jì)模式。
對設(shè)計(jì)模式感興趣而且希望隨學(xué)隨用的讀者通過本書可以快速跨越從理解到運(yùn)用的門檻;希望學(xué)習(xí)Python GUI 編程的讀者可以將本書中的示例作為設(shè)計(jì)和開發(fā)的參考;使用Python 語言進(jìn)行圖像分析、數(shù)據(jù)處理工作的讀者可以直接以本書中的示例為基礎(chǔ),迅速構(gòu)建自己的系統(tǒng)架構(gòu)。
覺得本文有幫助?請分享給更多人。
關(guān)注微信公眾號【面向?qū)ο笏伎肌枯p松學(xué)習(xí)每一天!
面向?qū)ο箝_發(fā),面向?qū)ο笏伎迹?/span>
