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.
拋異常聲明讓錯(cuò)誤處理更脆弱,強(qiáng)制產(chǎn)生運(yùn)行時(shí)成本,已經(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的異常,就會(huì)激活意外的錯(cuò)誤處理,而這個(gè)處理的默認(rèn)動(dòng)作就是終止程序。那樣還好,假設(shè)我們已經(jīng)檢查過了,這種事情不會(huì)發(fā)生,這時(shí)如果f被修改為拋出一個(gè)新異常Z,系統(tǒng)馬上就會(huì)發(fā)生崩潰,除非我們修改use()(并且重新進(jìn)行完整測(cè)試)。麻煩在于f()可能處于某個(gè)我們無法控制的功能庫(kù)中,而且對(duì)于新異常use()也沒有什么可做的,或者根本就不感興趣。我可以修改use()將Z傳出,但是接下來user()的調(diào)用者可能需要跟著修改。情況很快就會(huì)失控。或者我們可以為use()增加try-catch結(jié)構(gòu)將Z映射到一個(gè)可以接受的異常。情況很快會(huì)再次失控。注意成組修改異常經(jīng)常發(fā)生在系統(tǒng)的底層(例如由于網(wǎng)絡(luò)庫(kù)或某個(gè)中間件發(fā)生變化),因此變更會(huì)像氣泡一樣向上傳遞至整個(gè)調(diào)用鏈。在大規(guī)模代碼中,這可能意味著沒有人可以將庫(kù)更新到新版本,直到最后的調(diào)用者發(fā)生變更。如果use()是庫(kù)的一部分,它可能無法更新,因?yàn)檫@種變更不知道會(huì)影響誰。
The policy of letting exceptions propagate until they reach a function that potentially can handle it has proven itself over the years.
讓異常傳播直至一個(gè)有可能處理它的函數(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().
如果不會(huì)拋出任何異常,使用noexcept或者和它等價(jià)的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í)行的示例對(duì)23 個(gè)設(shè)計(jì)模式逐個(gè)進(jìn)行說明。這樣一方面可以使讀者了解真實(shí)的軟件開發(fā)工作中每個(gè)設(shè)計(jì)模式的運(yùn)用場(chǎng)景和想要解決的問題;另一方面通過對(duì)這些問題的解決過程進(jìn)行說明,讓讀者明白在編寫代碼時(shí)如何判斷使用設(shè)計(jì)模式的利弊,并合理運(yùn)用設(shè)計(jì)模式。
對(duì)設(shè)計(jì)模式感興趣而且希望隨學(xué)隨用的讀者通過本書可以快速跨越從理解到運(yùn)用的門檻;希望學(xué)習(xí)Python GUI 編程的讀者可以將本書中的示例作為設(shè)計(jì)和開發(fā)的參考;使用Python 語(yǔ)言進(jìn)行圖像分析、數(shù)據(jù)處理工作的讀者可以直接以本書中的示例為基礎(chǔ),迅速構(gòu)建自己的系統(tǒng)架構(gòu)。
覺得本文有幫助?請(qǐng)分享給更多人。
關(guān)注微信公眾號(hào)【面向?qū)ο笏伎肌枯p松學(xué)習(xí)每一天!
面向?qū)ο箝_發(fā),面向?qū)ο笏伎迹?/span>
