2010-09-04 53 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