【发布时间】:2014-07-21 05:48:29
【问题描述】:
我正在尝试编写一个在系统调用失败时需要抛出的异常类。异常应该有一个开发者消息和错误代码,它的what 方法应该与错误代码一起格式化开发者消息。进行格式化的 C 方法是 snprintf,但我试图避免这种情况。我尝试为std::stringstream 类型的异常定义一个类成员。但是,这不起作用,因为stringstream 有一个私有复制构造函数。寻找替代方案我了解了 Boost 的格式对象。我尝试使用它并得到一个不同的错误:
In file included from tun_device.cc:7:0:
system_error.h:9:7: error: looser throw specifier for ‘virtual SystemError::~SystemError()’
class SystemError : public exception
^
In file included from system_error.h:4:0,
from tun_device.cc:7:
/usr/include/c++/4.8/exception:64:13: error: overriding ‘virtual std::exception::~exception() throw ()’
virtual ~exception() _GLIBCXX_USE_NOEXCEPT;
解决这个问题的方法是定义我自己的析构函数:
~SystemError() throw() {
}
据我了解,此行指定此异常的析构函数不应抛出任何异常。
这是完整的课程:
class SystemError : public exception
{
public:
int m_errno;
const char * m_message;
SystemError(int err, const char * message) :
fmt("%1%: %2%") {
fmt % message % errno;
m_errno = err;
this->m_message = message;
}
const char * what() const throw(){
return fmt.str().c_str();
}
~SystemError() throw() {
}
private:
format fmt;
};
我有几个问题:
首先 - 我是在重新发明轮子吗?是否已经有推荐的 C++ 方法来处理失败的系统调用?
为什么使用
format类作为异常成员会强制我覆盖默认析构函数?现在我添加了自己的析构函数,有什么陷阱需要注意吗?
有没有办法只使用标准 C++ 库来实现我想要的?
【问题讨论】:
-
我会将
fmt设为静态,因为它可以被SystemError的所有实例共享并在what()中进行格式化。 -
不要为每个实例添加比绝对必要的更多的异常。不需要格式化程序。
-
@KhouriGiordano - 这是一个有趣的想法。如果我理解正确,那么它不是线程安全的。我错了吗?
-
解析传递给格式ctor的字符串需要时间,但是制作静态的本地副本将是快速且线程安全的。现在我想了想,我不会在异常本身中进行任何格式化,仅当它通过控制台、日志文件等呈现给用户时。
-
Khouri 你是在认真谈论过早优化异常处理吗?
标签: c++ boost custom-exceptions