throw;
重新抛出它捕获的同一异常对象,而throw ex;
则抛出一个新的异常。这并没有区别,除了创建一个新的异常对象的性能原因。如果您有一个异常层次结构,其中有一些其他异常类派生自MyException
类,并且在抛出异常时,您使用了throw DerivedClassException;
,那么它可以被catch(MyException&)
捕获。现在,如果您修改此已捕获的异常对象并使用throw;
重新抛出它,则异常对象的类型仍将是DerivedClassException
。如果您使用throw Ex;
,则会发生对象切片,新抛出的异常将是MyException
类型。
throw;
可以帮你保存原始异常,因为它会重新抛出原始异常。 - philsquared[C++ FAQ Lite § 17.9]
throw;
是什么意思?在哪里会用到它?你可能会看到类似以下的代码:
class MyException {
public:
...
void addInfo(const std::string& info);
...
};
void f()
{
try {
...
}
catch (MyException& e) {
e.addInfo("f() failed");
throw;
}
}
在这个例子中,语句throw;
的意思是“重新抛出当前异常”。在这里,一个函数通过非常量引用捕获了一个异常,修改了异常(添加信息),然后重新抛出了异常。通过在程序的重要函数中添加适当的catch子句,可以使用这种习惯用法来实现简单形式的堆栈跟踪。void handleException()
{
try {
throw;
}
catch (MyException& e) {
...code to handle MyException...
}
catch (YourException& e) {
...code to handle YourException...
}
}
void f()
{
try {
...something that might throw...
}
catch (...) {
handleException();
}
}
这个习惯用法允许在多个函数中重复使用单个函数(handleException()
)来处理异常。catch(MyException& ex) { throw ex; }
可能会复制 ex
,因此可能带来某些问题。 而 catch(MyException& ex) { throw; }
则不会。如果您有一个异常层次结构,throw ex
可能会切断您的异常,而throw
则不会。例如:
#include <iostream>
#include <string>
using namespace std;
struct base
{
virtual string who() {return "base";}
};
struct derived : public base
{
string who() {return "derived";}
};
int main() {
try {
try {
throw derived(); // throws a 'derived'
}
catch (base& ex)
{
throw ex; // slices 'derived' object to be a 'base' object
}
}
catch (base& ex)
{
cout<<ex.who()<<endl; // prints 'base'
}
}
将 throw ex
更改为只有 throw
,就会得到一个输出结果为 derived
,这可能是您希望得到的结果。
catch(...)
中使用 throw;
格式(这是唯一的重新抛出异常的方式,如果您使用 catch(...) 捕获异常)。throw
意味着抛出当前处理的异常,而catch(...)
意味着捕获任何异常。 - David Thornley这有一个很大的区别。我在我的博客上写了一篇文章,链接是:https://cpptalk.wordpress.com/2009/08/23/nuances-of-exception-rethrow/
欢迎查看。
throw ex
会创建另一个副本,不建议使用。只使用throw
来抛出当前异常对象。
throw可以抛出非标准的异常类型,这些异常类型可以被catch(...)捕获(例如结构化异常)。
throw;
将中止程序。unexpected()
,除非另有规定(名称来自内存)。在这种情况下,裸 throw
和 throw something
有什么区别? - David Thornley