2

我有一些这样的代码:

class ParseError: public exception {

protected:

  mutable string msg;
  int position;

public:

  explicit ParseError(const string& message, const int index) {
    msg = message;
    position = index;
  }

  virtual ~ParseError() throw () {
  }

  const char * what() const throw () {
    stringstream ss(msg);
    ss << "Parse error at position " << position << ": " << msg;
    msg = ss.str();
    return msg.c_str();
  }

};

当我抛出它时,在 valgrind 下运行单元测试时会看到类似这样的内容:

foo.h:102:带有消息的意外异常:'第 9 位解析错误:发现意外字符:blah'

这就是我想要的,但我很好奇基exception类在幕后做了什么。如果我不扩展exception但保持课程的其余部分不变,我会得到:

foo.h:102:带有消息的意外异常:“未知异常”

我需要向我的班级添加什么才能无法扩展exception并仍然显示消息?

顺便说一句,我意识到我可能应该扩展runtime_error而不是exception. 在这种情况下,我很好奇exception幕后的原因是什么,我不一定要寻求有关最佳实践的建议。

4

2 回答 2

2

如果您不处理异常,则无法保证您会收到有用的错误消息;唯一的保证是程序将通过调用std::terminate.

您的实现似乎能够识别出未处理的异常是从 派生的std::exception,并使用该知识来调用其覆盖what()以生成错误消息。它对非标准异常类型一无所知,它不应该仅仅因为它们恰好与完全不相关的类中的函数具有相同的名称而随机调用函数。

如果你想在抛出任意类型时打印一些有用的东西,你需要一个处理程序来捕获该类型并用它做正确的事情。但我绝对建议你只抛出派生自的类型,std::exception除非你有很好的理由抛出其他东西。

于 2012-10-01T03:07:35.117 回答
1

这里有两个问题:

在这个函数中,你msg自己:

  const char * what() const throw () {
    stringstream ss(msg);
                 ** ^^^
    ss << "Parse error at position " << position << ": " << msg;
    **                                                      ^^^

但这并不是很重要,因为您的第二个问题是您应该将创建消息从what()构造函数移至构造函数。what()应该只返回它。

class ParseError: public exception {
protected:
  string msg;

public:
  explicit ParseError(const string& message, const int index) {
    ostringstream ss;
    ss << "Parse error at position " << position << ": " << message;
    msg << ss.str();
  }

  const char * what() const throw () {
    return msg.c_str();
  }

};
于 2012-10-01T03:53:18.043 回答