what() 不抛出异常(异常类)重要吗?
Is it important that what() does not throw (exception classes)?
C++ Primer 的练习要求
Why is it important that the what function [of exception classes] doesn’t throw?
由于无法检查我的回答,所以我希望得到意见。我认为在当前异常对象仍在处理时,在 catch 子句期间抛出另一个异常(而不是重新抛出 throw;
)可能是一个错误(可能会调用 terminate
)。似乎情况并非如此,完全可以抛出 catch 子句:
#include <iostream>
using namespace std;
int main(){
try{
try{
throw exception();
} catch(exception err){ throw exception();}
} catch(exception err){ cout << "caught"} //compiles and runs fine, outputs "caught"
}
所以程序终止不用担心。看来,任何由 what() 抛出引起的问题至少应该可以由用户纠正,如果他们愿意的话。
也许那么,重要的可能是在处理错误时我们不希望发生更多意外错误? throws inside catch 子句主要用于将异常对象发送到调用链的更上游。用户可能会从他的程序深处收到一个错误,并且不想担心捕获到的错误必须与其自己的 try 块相关联。或者 what() 有自己的 throw 也可能导致递归效果(例如 what() 抛出异常,然后我们捕获这个异常并调用 what() 但是这然后抛出,等等)意味着它可能变得无法处理有什么错误吗? what() 可能会抛出多剧烈?
我认为没有什么不清楚的-正如您所描述的那样。如果异常 class 的 .what()
方法抛出错误,则整个 catch
的努力都被浪费了 :
try {
someDangerousOperation();
}
catch(std::exception e) {
// Ooops, instead of false,
//we get another exception totally unrelated to original error
someLogClassOrWhatever.save(e.what());
return false;
}
return true;
想象一下,如果您要处理 what()
的异常,那会是多么疯狂的代码:
try {
someDangerousOperation();
}
catch(std::exception e) {
// Not very fun
try {
someLogClassOrWhatever.save(e.what());
}
catch(...) {
alsoWhatHasFailedThatIsReallyGreat();
}
return false;
}
我觉得没什么了不起的,可能问题太简单了,看来一定有什么隐患。我觉得不是这样的。
想象一个非常好奇的编码员,有轻微的控制狂倾向(我自己认识其中几个),他真的很想知道他的程序出了什么问题,并用 [=25= 记录所有错误]()。所以他编码
try {
code();
}
catch(std::exception &e) {
std::cout<<e.what()
}
他对整个世界,尤其是对自己都非常满意。但现在他突然想到,e.what() 也可能抛出异常。所以他是代码:
try{
try {
code();
}
catch(std::exception &e) {
std::cout<<e.what()
}
}
catch(std::exception &e) {
std::cout<<e.what()
}
一分钟后他注意到,可能又出现了未捕获的异常!记住,他是个控制狂,所以他要写另一个 try-catch 块,然后再写一个又一个
所以你可以赌任何钱,他的项目会延迟——你怎么能这样对我的朋友?所以请确保 e.what()
不会抛出:)
我想这就是 what
是 noexcept 的原因。
std::exception::what()
不例外。因此,如果它抛出, std::terminate
就会被调用。是的,这很重要。
C++ Primer 的练习要求
Why is it important that the what function [of exception classes] doesn’t throw?
由于无法检查我的回答,所以我希望得到意见。我认为在当前异常对象仍在处理时,在 catch 子句期间抛出另一个异常(而不是重新抛出 throw;
)可能是一个错误(可能会调用 terminate
)。似乎情况并非如此,完全可以抛出 catch 子句:
#include <iostream>
using namespace std;
int main(){
try{
try{
throw exception();
} catch(exception err){ throw exception();}
} catch(exception err){ cout << "caught"} //compiles and runs fine, outputs "caught"
}
所以程序终止不用担心。看来,任何由 what() 抛出引起的问题至少应该可以由用户纠正,如果他们愿意的话。
也许那么,重要的可能是在处理错误时我们不希望发生更多意外错误? throws inside catch 子句主要用于将异常对象发送到调用链的更上游。用户可能会从他的程序深处收到一个错误,并且不想担心捕获到的错误必须与其自己的 try 块相关联。或者 what() 有自己的 throw 也可能导致递归效果(例如 what() 抛出异常,然后我们捕获这个异常并调用 what() 但是这然后抛出,等等)意味着它可能变得无法处理有什么错误吗? what() 可能会抛出多剧烈?
我认为没有什么不清楚的-正如您所描述的那样。如果异常 class 的 .what()
方法抛出错误,则整个 catch
的努力都被浪费了 :
try {
someDangerousOperation();
}
catch(std::exception e) {
// Ooops, instead of false,
//we get another exception totally unrelated to original error
someLogClassOrWhatever.save(e.what());
return false;
}
return true;
想象一下,如果您要处理 what()
的异常,那会是多么疯狂的代码:
try {
someDangerousOperation();
}
catch(std::exception e) {
// Not very fun
try {
someLogClassOrWhatever.save(e.what());
}
catch(...) {
alsoWhatHasFailedThatIsReallyGreat();
}
return false;
}
我觉得没什么了不起的,可能问题太简单了,看来一定有什么隐患。我觉得不是这样的。
想象一个非常好奇的编码员,有轻微的控制狂倾向(我自己认识其中几个),他真的很想知道他的程序出了什么问题,并用 [=25= 记录所有错误]()。所以他编码
try {
code();
}
catch(std::exception &e) {
std::cout<<e.what()
}
他对整个世界,尤其是对自己都非常满意。但现在他突然想到,e.what() 也可能抛出异常。所以他是代码:
try{
try {
code();
}
catch(std::exception &e) {
std::cout<<e.what()
}
}
catch(std::exception &e) {
std::cout<<e.what()
}
一分钟后他注意到,可能又出现了未捕获的异常!记住,他是个控制狂,所以他要写另一个 try-catch 块,然后再写一个又一个
所以你可以赌任何钱,他的项目会延迟——你怎么能这样对我的朋友?所以请确保 e.what()
不会抛出:)
我想这就是 what
是 noexcept 的原因。
std::exception::what()
不例外。因此,如果它抛出, std::terminate
就会被调用。是的,这很重要。