此时我确信我应该为所有异常抛出需求创建std::exception
的子类。现在我正在研究如何覆盖what
方法。
我所面临的情况,如果字符串what
返回是动态的,那将非常方便。例如,某些代码解析XML文件,并在错误消息中添加位置或行号对我很有用。
我正在尝试关注Boost Exception handling guidelines。
我想知道的事情:
what
返回const char *
,这意味着任何捕手都可能不会释放该字符串。所以我需要一些其他的地方来存储结果,但那会是哪里? (我需要线程安全。)
what
在其签名中还包含throw()
。虽然我可以阻止我的what
投掷任何东西,但在我看来,这种方法实际上不适用于任何过于动态的东西。如果what
不是正确的地方,那么我应该在哪里做这个呢?
从我到目前为止得到的答案看来,实现这一目标的唯一方法是将字符串存储在异常中。 Boost指南建议不要这样做,这让我感到困惑,因为std::runtime_error
就是这样。
即使我要使用C字符串,我也必须使用静态大小的缓冲区,或进行内存管理,这也会失败。 (我想知道这是否是std::string
的复制构造函数中唯一可能出错的问题。这意味着我不会使用动态分配的C字符串获得任何东西。)
还有其他选择吗?
答案 0 :(得分:16)
我的异常类通常除了构造函数之外没有任何东西,并且看起来是这样的:
class MyEx: public std::runtime_error
{
public:
MyEx(const std::string& msg, int line):
std::runtime_error(msg + " on line " + boost::lexical_cast<string>(line))
{}
};
任意示例,但它是处理what()
消息管理的基类。
但是如果你愿意,你也可以在构造函数体中汇总消息后,只分配异常对象的基本部分。
#include <stdexcept>
#include <string>
#include <sstream>
class MyEx: public std::runtime_error
{
public:
MyEx(const std::string& msg, int line):
std::runtime_error("")
{
std::stringstream ss;
ss << msg << " on line " << line;
static_cast<std::runtime_error&>(*this) = std::runtime_error(ss.str());
}
};
#include <iostream>
int main()
{
try {
throw MyEx("Evil code", __LINE__);
}
catch (const std::exception& e) {
std::cout << e.what() << '\n';
}
}
但是,关于boost的指导方针,也许您应该注意数字数据(位置和线)最好通过其他方法作为数字提供的点。指南说,不要担心what()
消息。
答案 1 :(得分:6)
Boost的指南似乎基于两个假设:复制异常对象可能会引发另一个异常,而what()字符串不是一个强大或可靠的工具。如果您正在编写一个可以在各种环境中广泛使用的库,这些都是有效的问题。如果您更好地了解如何使用该例外,您可以判断这些问题是否合理或者无关紧要。编程是关于一系列的权衡,对Boost开发人员有意义的权衡可能不适用于你。
答案 2 :(得分:3)
嗯,没问题,你可以简单地实现派生异常类的构造函数来格式化你将从what()返回的字符串。释放析构函数中用于缓冲区的缓冲区。
答案 3 :(得分:1)
我接受了UncleBens的回答,因为我认为它在技术上是对我原始问题的最正确和最完整的答案。
作为参考,我实际上选择了一个不同的解决方案,并完全停止使用what
。我已经重构了我现在使用的代码作为基本异常类:
struct Exception : public virtual std::exception
{
virtual const char* what() const throw()
{
try {
return typeid(this).name();
}
catch (const std::exception& e) {
return "<unknown exception>";
}
}
// Extended description; may throw.
virtual void describe(std::ostream& out) const = 0;
};
基本上只是填充what
我能找到的最有意义的东西,而不用在其他任何地方打扰它。我猜我会看到这种票价。