【问题标题】:Problem throwing and catching custom exceptions in C++在 C++ 中引发和捕获自定义异常的问题
【发布时间】:2011-06-12 20:00:53
【问题描述】:

我创建了类Someting,它在实例化失败时会抛出异常SomethingException(SomethingException 继承自std::exception)。问题是我不能像这样捕获 SomethingException (我不得不做一个肮脏的把戏来捕获它)。

在程序中的某个地方执行: 这不起作用,没有捕获到异常,程序崩溃了。

try{
    Something* s = new Something();
}
catch (SomethingException* e){
    std::cerr<<e.what();
}

相比之下,这确实有效(异常被捕获并显示正确的消息)但我真的觉得我不应该这样做

try{
    Something* s = new Something();
}
catch (std::exception* e){
    SomethingException* e2 = (SomethingException*) e;
    std::cerr<<e.what();
}

因为指针是强制转换的,所以只有当且仅当抛出一种类型的异常时,我才能使其工作。当我需要捕捉各种类型时,这将不起作用。

有没有办法以更正确的方式捕获自定义异常?

编辑:

抛出异常如下

//...
throw new SomethingException ("Errormessage"); //Custom exception constructor
//...

Something::Something() 的声明是

Something::Something() throw(...)

使用声明

Something::Something() throw(SomethingException)
//or
Something::Something() throw(SomethingException*)

引发大量警告(警告 C4290)

【问题讨论】:

  • 你为什么抛出一个指针而不是by value
  • 您的代码感觉就像您是一个从 C++ 开始的 Java 程序员。你使用异常的方式不是通常的 C++ 方式。
  • 注意:从 std::runtime_error 派生异常比从 std::exception 更容易。这是因为 std::runtime_error 将为您存储由 what() 方法返回的错误消息(在构造函数中传递)。注意:MSVC 有一个非标准的 std::exception 允许您在构造函数中传递错误消息。

标签: c++ exception try-catch


【解决方案1】:

一般来说,最好是按值抛出异常并通过引用捕获它们:

try {

    throw SomethingException();

} catch (const SomethingException& error) {

    std::cerr << error.what() << '\n';

}

如果你用throw new SomethingException() 抛出异常,你只能用catch (SomethingException*) 捕获异常。您的问题中没有足够的信息可以说明,但问题可能在于SomethingException 是如何从std::exception 派生的。验证或将其更改为继承自 std::runtime_errorstd::logic_error

另外,不要使用throw 说明符。只是不要。没有编译器为使用检查异常提供任何好处:实际上,检查异常不会被检查,除非在发生不符合说明符的异常时会严重失败(抛出 std::bad_exception) .这可能就是您的代码中发生的情况。

【讨论】:

  • > throw new SomethingException() 是抛出的方式。反正我会试试你说的
  • 这一次它根本不编译。 'std::runtime_exception 没有默认构造函数' 编译器也会抛出警告说'省略异常规范,除非断言函数不是 __declspec(nothrow)'
  • @NeonMan:runtime_errorlogic_error 构造函数接收 string 消息,如果重载,what() 必须具有 throw() 说明符。
  • @NeonMan:你应该去掉函数上的throw(SomethingException) 说明符。捕获用户定义的异常确实没有理由无法正常工作,并且您的帖子中没有足够的信息来说明您的问题所在。
  • @NeonMan:我建议在函数声明中不要抛出任何说明符,是的,在函数体中使用throw SomethingException();
【解决方案2】:

对于可能遇到从 std::exception 派生的自定义异常被抛出但未被捕获的问题的其他人,请检查: - 继承是公开的 - 如果您的异常在另一个 DLL 中声明,则该异常类是从 DLL 导出的。奇怪的是,如果不是,这不会产生链接错误(在 VS2012 中),它只是无法被捕获。

【讨论】:

  • 这对 GCC 也有帮助(在自定义异常声明中的 : 之后添加 public)。
【解决方案3】:

你能显示你抛出异常的代码吗?

另一点是关于 throw-specifications - 这通常是一个坏主意。问题是,与 Java 不同,C++ 不坚持抛出规范,因此您几乎不会从它们中受益。如果您的代码(或您调用的某些代码)抛出了 throw-spec 中未指定的异常,他们所能做的就是可能导致核心转储

【讨论】:

  • 添加了投掷线。与 c++ 不同,我真的很喜欢 java 使用异常的方式。在这种情况下,防止对象被构造是必不可少的,并且最好使用自定义异常。
猜你喜欢
  • 2011-01-31
  • 1970-01-01
  • 2011-09-22
  • 2011-04-19
  • 2015-06-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多