【发布时间】:2011-04-08 04:34:27
【问题描述】:
我可以得到一个被捕获的异常的描述
catch(...)
阻止?类似于 std::exception 的 .what()。
【问题讨论】:
-
在 C++11 中重新抛出
std::current_exception可用于在 catch-all 块中获取what异常消息:stackoverflow.com/a/37222762/5447906
我可以得到一个被捕获的异常的描述
catch(...)
阻止?类似于 std::exception 的 .what()。
【问题讨论】:
std::current_exception 可用于在 catch-all 块中获取 what 异常消息:stackoverflow.com/a/37222762/5447906
你可以使用一个技巧:
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";
}
等等,你认为可能会抛出尽可能多的不同类型。如果您真的对可能抛出的内容一无所知,那么即使倒数第二个也是错误的,因为有人可能会抛出一个不指向以 nul 结尾的字符串的char*。
抛出任何不是std::exception 或派生类的东西通常是个坏主意。 std::exception 存在的原因是允许每个人投掷和捕捉他们可以做一些有用的事情的对象。在一个玩具程序中,您只想离开那里,甚至懒得包含标准标题,好吧,也许抛出一个int 或字符串文字。我认为我不会将其作为正式界面的一部分。您抛出的任何异常都是正式界面的一部分,即使您不知何故忘记记录它们。
【讨论】:
catch(...){} 中输入新的try-block 并重新抛出异常以确定其类型。)
throw 的效果(重新抛出当前异常)。
该块可能会捕获一个 int、一个 const char* 或任何东西。当编译器对它一无所知时,它怎么可能知道如何描述它呢?如果你想从异常中获取信息,你必须知道它的类型。
【讨论】:
__what() 返回一个字符串,其中包含当前异常的类型信息名称(易于实现),后跟更多描述其值的字符(实际上你可以很容易但相当乏味地涵盖了内置类型和大多数标准库,并且可能有一些用户定义类型的基本实现)。当然,这意味着编译器会为每种类型发出一些臃肿的代码来进行字符串转换,但是想想已经有多少operator<<。为所有事情都这样做,当然是不可能的。
如果你知道你只抛出 std::exception 或子类,试试
catch(std::exception& e) {...e.what()... }
否则,正如 DeadMG 所写,由于您可以(几乎)扔掉所有东西,因此您无法假设您捕获的东西。
通常,catch(...) 仅应在使用编写不当或文档记录不佳的外部库时用作最后一道防线。所以你会使用层次结构
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");
}
【讨论】:
从 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)
{
}
【讨论】:
我们实现异常的方式是,我们有自己的异常类,它们都派生自std::exception..
我们的异常将包含异常消息、函数名、文件名和生成异常的行。这些都非常有用,不仅可以显示消息,还可以用于日志记录,这有助于很容易地诊断异常。因此,我们获得了有关生成的异常的全部信息。
请记住,我们可以获取有关问题所在的信息。所以,在这方面,每一点信息都有帮助..
【讨论】:
引用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;
}
【讨论】:
std::exception_ptr 是一个指向 unspecified 类型的智能共享指针,因此不能保证 __cxa_exception_type() 存在