2010-09-04 54 views
21

我可以通過c + +被捲進捕捉異常(...)塊

catch(...) 

塊捕獲的異常的描述的描述?類似於。std :: exception的what()

+1

在C++ 11的'重新拋出std :: current_exception'可用於在catch-all塊中獲取異常的whats消息:http://stackoverflow.com/a/372​​22762/5447906 – 2016-05-15 04:46:06

回答

38

有一個竅門,你也許可以使用:

catch(...) { 
    handle_exception(); 
} 

void handle_exception() { 
    try { 
     throw; 
    } catch (const std::exception &e) { 
     std::cout << e.what() << "\n"; 
    } catch (const int i) { 
     std::cout << i << "\n"; 
    } catch (const long l) { 
     std::cout << l << "\n"; 
    } catch (const char *p) { 
     std::cout << p << "\n"; 
    } catch (...) { 
     std::cout << "nope, sorry, I really have no clue what that is\n"; 
    } 

等,儘可能多的不同類型,你認爲可能會被拋出。如果你對拋出的東西一無所知,那麼即使倒數第二個也是錯誤的,因爲有人可能拋出一個char*,它不指向一個以nul結尾的字符串。

扔什麼不是std::exception或派生類通常是一個壞主意。 std::exception存在的原因是爲了讓每個人都可以拋出並捕獲可以做一些有用的事物。在一個玩具程序中,你只是想離開那裏,甚至不會被打擾包括一個標準的頭,OK,可能會拋出一個int或字符串文字。我不認爲我會做出正式界面的一部分。你拋出的任何異常都是你的正式界面的一部分,即使你忘記記錄它們。

+2

嗨;這是一個很好的答案。我一直在尋找一些時間在標準文件中找到證據,證明這是標準行爲,但一直沒有找到。你確定知道這是標準行爲嗎? (也就是在catch(...){}內輸入一個新的'try'-block並重新拋出一個異常以確定它的類型。) – NHDaly 2013-11-13 17:10:19

+1

從內存開始工作:查找關於當前的異常(直到你退出catch子句),以及沒有操作數的throw(拋出當前異常)的效果。 – 2013-11-13 21:56:07

5

該塊可能會捕獲一個int或一個const char *,或任何東西。編譯器如何能夠知道如何描述一些事情,但它對此一無所知?如果你想從異常中獲得信息,你必須知道類型。

+5

「編譯器如何知道如何描述它知道的東西沒有關係?「 - +1,但實際上,編譯器確實知道一點。異常機制必須存儲* some *類型的信息,因爲它必須將異常對象與catch子句相匹配。但該標準沒有定義這些信息或提供對它的訪問,這是一個隱藏的實現細節。 – 2010-09-04 10:09:51

+0

該類型的信息遠遠不足以執行此操作,並且沒有任何實現可以改變這一點。 – Puppy 2014-09-18 08:36:14

+1

聽起來像是一個挑戰;-)一個編譯器擴展'__what()'返回一個字符串,其中包含當前異常的typeinfo名稱(易於實現),後面跟着更多描述其值的字符(實際上,您可以輕鬆但相當繁瑣地覆蓋內建類型和大部分標準庫,並且可能有一些用戶定義類型的基本實現)。當然,這意味着編譯器會爲每個類型發佈一些龐大的代碼來進行字符串轉換,但是後來想一想那裏已經有多少'operator <<'。爲所有事做,當然不可能。 – 2014-09-18 08:52:15

4

如果你知道你只能扔的std ::異常或子類,嘗試

catch(std::exception& e) {...e.what()... } 

否則,DeadMG寫道,因爲你可以扔掉(幾乎)一切,你不能假設你抓住了什麼東西。

正常情況下,捕獲(...)只能用作最後的防禦措施,當使用錯誤的書面或記錄的外部庫時。所以,你會使用一個層次

catch(my::specialException& e) { 
     // I know what happened and can handle it 
     ... handle special case 
     } 
catch(my::otherSpecialException& e) { 
     // I know what happened and can handle it 
     ... handle other special case 
     } 
catch(std::exception& e) { 
     //I can at least do something with it 
     logger.out(e.what()); 
     } 
catch(...) { 
    // something happened that should not have 
    logger.out("oops"); 
    } 
2

如何我們有例外實現的是,我們有我們自己的異常類,即都是從std::exception衍生..

我們的例外將包含異常消息,功能名稱,文件名和行生成異常。這些都不僅有助於顯示消息,還可以用於日誌記錄,它可以幫助您輕鬆診斷異常。所以,我們得到關於生成的例外的全部信息。

還記得例外是我們得到有關錯誤的信息。因此,信息的每一點幫助在這方面..

3

由於C++ 11,你可以捕捉當前異常的指針:

std::exception_ptr p;  // default initialization is to nullptr 

try { 
     throw 7; 
} 
catch(...) 
{ 
    p = std::current_exception(); 
} 

這就像一個智能指針;只要至少有一個指向異常對象的指針就不會被銷燬。

以後(甚至在不同的功能),你就可以採取行動以類似的方式,以目前的頂級答案:

try { 
    if (p) 
     std::rethrow_exception(p); 
} 
catch(int x) 
{ 

} 
catch(std::exception &y) 
{ 
} 
2

報價bobah

#include <iostream> 

#include <exception> 
#include <typeinfo> 
#include <stdexcept> 

int main() 
{ 
    try { 
     throw ...; // throw something 
    } 
    catch(...) 
    { 
     std::exception_ptr p = std::current_exception(); 
     std::clog <<(p ? p.__cxa_exception_type()->name() : "null") << std::endl; 
    } 
    return 1; 
} 
+1

這不是標準或便攜式。它依賴於編譯器之間不同的*實現特定細節*。 'std :: exception_ptr'是一個聰明的指向* unspecified *類型的共享指針,所以不能保證存在'__cxa_exception_type()' – 2017-11-30 19:03:23