我有一些像这样的代码:
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
在幕后打勾,我不一定在寻找有关最佳实践的建议。
答案 0 :(得分:2)
如果您不处理异常,则无法保证您会收到有用的错误消息;唯一的保证是通过致电std::terminate
来终止该计划。
您的实现似乎能够识别未处理的异常是从std::exception
派生的,并使用该知识调用其覆盖what()
来生成错误消息。它对非标准异常类型一无所知,它不应该随意调用函数,因为它们碰巧与完全无关的类中的函数具有相同的名称。
如果要在抛出任意类型时打印有用的东西,则需要一个处理程序来捕获该类型并使用它执行正确的操作。但我肯定会建议你只抛出从std::exception
派生的类型,除非你有充分的理由抛出别的东西。
答案 1 :(得分: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();
}
};