亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

我應該在C ++中使用異常說明符嗎?

我應該在C ++中使用異常說明符嗎?

C++
慕婉清6462132 2019-10-25 10:46:55
在C ++中,您可以使用異常說明符來指定一個函數可能會拋出異常,也可能不會拋出異常。例如:void foo() throw(); // guaranteed not to throw an exceptionvoid bar() throw(int); // may throw an exception of type intvoid baz() throw(...); // may throw an exception of some unspecified type由于以下原因,我對實際使用它們表示懷疑:編譯器實際上并沒有以任何嚴格的方式強制執行異常說明符,因此好處并不大。理想情況下,您希望獲得一個編譯錯誤。如果函數違反異常說明符,我認為標準行為是終止程序。在VS.Net中,它將throw(X)視為throw(...),因此對標準的遵循性不強。您認為應該使用異常說明符嗎?請回答“是”或“否”,并提供一些理由來證明您的回答合理。
查看完整描述

3 回答

?
慕的地8271018

TA貢獻1796條經驗 獲得超4個贊

沒有。


這里有幾個例子說明為什么:


模板代碼無法使用異常規范編寫,


template<class T>

void f( T k )

{

     T x( k );

     x.x();

}

副本可能會拋出,參數傳遞可能會拋出,并且x()可能會拋出一些未知異常。


異常規范傾向于禁止可擴展性。


virtual void open() throw( FileNotFound );

可能演變成


virtual void open() throw( FileNotFound, SocketNotReady, InterprocessObjectNotImplemented, HardwareUnresponsive );

你真的可以寫成


throw( ... )

第一個是不可擴展的,第二個是過于雄心勃勃的,第三個實際上是您在編寫虛擬函數時的意思。


舊版代碼


當您編寫依賴于另一個庫的代碼時,您真的不知道當發生嚴重錯誤時它可能會做什么。


int lib_f();


void g() throw( k_too_small_exception )

   int k = lib_f();

   if( k < 0 ) throw k_too_small_exception();

}

glib_f()拋出時將終止。(在大多數情況下)這不是您真正想要的。std::terminate()永遠不應該被調用??偸亲寫贸绦蛞蛭刺幚淼漠惓6罎ⅲ◤闹锌梢詸z索堆棧跟蹤)總是比靜默/劇烈地消亡更好。


編寫返回常見錯誤并在特殊情況下拋出的代碼。


Error e = open( "bla.txt" );

if( e == FileNotFound )

    MessageUser( "File bla.txt not found" );

if( e == AccessDenied )

    MessageUser( "Failed to open bla.txt, because we don't have read rights ..." );

if( e != Success )

    MessageUser( "Failed due to some other error, error code = " + itoa( e ) );


try

{

   std::vector<TObj> k( 1000 );

   // ...

}

catch( const bad_alloc& b )

   MessageUser( "out of memory, exiting process" );

   throw;

}

但是,當您的庫僅引發您自己的異常時,您可以使用異常規范說明您的意圖。


查看完整回答
反對 回復 2019-10-25
?
烙印99

TA貢獻1829條經驗 獲得超13個贊

我認為除約定外(對于C ++),標準

例外說明符是在C ++標準中進行的一項實驗,多數失敗。

唯一的例外是,不拋出說明符很有用,但您還應該在內部添加適當的try catch塊,以確保代碼與說明符匹配。Herb Sutter在此頁面上有一個頁面。戈特82


另外,我認為值得描述例外保證。


這些基本上是有關對象的狀態如何受到異常轉義的方法的文檔。不幸的是,它們沒有被編譯器強制執行或以其他方式提及。

提升和例外


例外保證

不保證:

在異常轉義方法之后,無法保證對象的狀態。

在這些情況下,不應再使用該對象。


基本保證:

在幾乎所有情況下,這都應該是方法提供的最低保證。

這保證了對象的狀態定義正確,并且仍然可以被一致地使用。


強有力的保證:(又名交易保證)

這保證了該方法將成功完成,

否則將引發異常并且對象狀態不會更改。


無投擲保證:

該方法保證不允許異常傳播到該方法之外。

所有破壞者都應作出此保證。

| 注意:如果在已傳播異常的情況下異常逃逸了析構函數

| 該應用程序將終止


查看完整回答
反對 回復 2019-10-25
?
波斯汪

TA貢獻1811條經驗 獲得超4個贊

異常規范不是C ++中非常有用的工具。但是,如果與std :: unexpected結合使用,則/ is /有很好的用途。

在某些項目中,我要做的是編寫具有異常規范的代碼,然后使用將拋出我自己設計的特殊異常的函數調用set_unexpected()。構造后,此異常獲取回溯(以特定于平臺的方式),并從std :: bad_exception派生(如果需要,可以傳播該異常)。如果它像往常一樣引起了一個terate()調用,則回溯將由what()打?。ㄒ约耙鹚脑籍惓#徊浑y發現),因此我獲得了合同所在位置的信息。違反,例如引發了意外的庫異常。

如果這樣做,我將永遠不允許傳播庫異常(std異常除外),并從std :: exception派生我的所有異常。如果庫決定拋出,我將捕獲并轉換為自己的層次結構,從而使我能夠始終控制代碼。由于明顯的原因,調用依賴函數的模板化函數應避免使用異常規范。但是無論如何,很少有帶有庫代碼的模板化函數接口(很少有庫確實以有用的方式使用模板)。


查看完整回答
反對 回復 2019-10-25
  • 3 回答
  • 0 關注
  • 438 瀏覽

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號