【问题标题】:Is it important that what() does not throw (exception classes)?what() 不抛出(异常类)重要吗?
【发布时间】:2016-01-14 21:55:22
【问题描述】:

C++ Primer 中的一个练习题

为什么 [异常类] 的 what 函数不抛出很重要?

由于无法检查我的答案,我希望得到意见。我认为在当前异常对象仍在处理时,在 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() 抛出的任何问题至少应该由用户纠正,如果他们愿意的话。

也许那么重要的是,在处理错误时,我们不希望发生更多意外错误? catch 子句中的抛出主要用于将异常对象进一步发送到调用链的上游。用户可能会从他的程序深处收到一个错误,并且不想担心捕获的错误必须与它自己的 try 块相关联。或者可能 what() 有自己的 throw 也可能导致递归效果(例如 what() 抛出一个异常,然后我们捕获这个异常并调用 what() 但这然后抛出,等等)意味着它可能变得无法处理有什么错误吗? what() 可能会抛出多厉害?

【问题讨论】:

  • 如果您在尝试处理第一个异常时遇到完全不相关的异常,则您基本上失去了处理第一个异常的所有能力,因为下一个catch 只会看到第二个异常。
  • what 用于确定它是什么类型的异常(因此您可以决定如何处理它)。投掷是不公平的,结果只会发生坏事。当然 BT 总是会发生 - 你的处理器着火了,但“什么”作者不能将异常作为其异常的正常行为的一部分
  • std::exception::what() 是例外。这个问题应该是心理锻炼还是..?

标签: c++ c++11 exception throw


【解决方案1】:

我认为没有什么不清楚的——正如你所描述的那样。如果异常类的.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;
}

我认为没有更多的东西,可能问题是如此简单,似乎其中隐藏了一些问题。我觉得不是这样的。

【讨论】:

  • 除非,如果 catch 块中的代码本身是在考虑异常安全的情况下编写的,他们可以记录 e.what() 抛出异常而不是返回异常的事实。什么都不会丢失。
  • 这是我发布的第二个代码。我评论了它Not very fun。在某些时候,try ... catch 块的数量高于程序员防止所有崩溃的动机......
  • 我宁愿认为 std::terminate 会在您不必担心任何数量的 try ... catch 块之前被调用...
  • @TomášZato 是的:自从我发表评论(或同时)以来,您修改了您的答案。好!
【解决方案2】:

std::exception::what() 不例外。因此,如果它抛出,std::terminate 会被调用。是的,这很重要。

【讨论】:

    【解决方案3】:

    想象一个非常好奇的编码器,有轻微的控制狂倾向(我自己认识几个),他真的想知道他的程序出了什么问题,并用 ex.what() 记录所有错误。所以他编码

    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 被排除在外的原因。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-06-16
      • 1970-01-01
      • 2011-11-02
      • 1970-01-01
      • 1970-01-01
      • 2021-06-28
      相关资源
      最近更新 更多