使用 C++ Boost 的格式对象作为异常成员
Using C++ Boost's format object as an exception member
我试图编写一个异常类,需要在系统调用失败时抛出。异常应该有一个开发人员消息和errno代码,它的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++库?
Exception可以使用标准的Exception类来处理,也可以从std:: Exception类派生出自己的类来处理。当您想要扩展使用std::exception已经可用的功能时,可以使用继承。所以这个决定完全取决于你想如何设计你的应用程序。
boost::format不会强制你重写析构函数。如果您注意到您正在从std::exception派生并组合boost::format。std::exception析构函数声明为虚函数,具有无抛出性质。
省略析构函数时,编译器隐式地提供一个析构函数,但该析构函数没有throw()性质,因此编译错误:
format.cpp:5: error: looser throw specifier for âvirtual SystemError::~SystemError()â
/usr/lib/gcc/x86_64-redhat-linux/4.4.7/../../../../include/c++/4.4.7/exception:63: error: overriding âvirtual std::exception::~exception() throw ()â
当你提供一个构造函数,但作为:
<>之前~ SystemError ();//由于基类std::exception有一个没有throw的析构函数,子类也应该遵循相同的析构函数,并且在这种情况下再次收到编译时错误:format.cpp:25: error: loose throw指定符::~SystemError()~SystemeError() throw();
SSCCE代码示例:
#include <iostream>
#include<boost/format.hpp>
class SystemError : public std::exception
{
public:
int m_errno;
const char * m_message;
SystemError(int err, const char * message) :
fmt("%1%: %2%") {
fmt % message % err;
m_errno = err;
this->m_message = message;
}
const char * what() const throw(){
return fmt.str().c_str();
}
~SystemError() throw() {
}
// ~SystemError() {
//
// }
private:
boost::format fmt;
};
int main(){
return 0;
}
添加析构函数就像是为你的行为承担责任。析构函数可用于清除类中分配的任何堆内存。缺少析构函数将导致编译器提供隐式析构函数,这可能在特定情况下导致问题。
如果所讨论的类具有基本数据类型,则不会收到编译错误。
- 是否允许分配器构造和销毁成员函数从内部逻辑引发异常?
- 在类声明中初始化 const 成员变量时在调试模式下出现异常
- 异常成员类 OOP
- 在字符串类上的成员函数和out_of_range异常处理
- 在使用 In Order 遍历成员函数时引发异常(堆栈溢出)时出现问题
- C++执行期间的类成员函数错误/异常处理
- 如果从类成员初始值设定项引发的异常调用 std::terminate()
- 从成员构造函数(Brace Initializer vs Initializer列表)抛出异常
- 在 C++ 中的构造函数中引发异常时销毁对象的成员变量
- 私有成员"current"的值在成员函数结束时发生异常更改
- 异常处理和成员变量
- C++C-tor处理默认成员值构造异常
- C++模板如果匹配类型else,则调用成员函数引发异常
- constexpr静态成员变量的异常行为
- 错误 C2248:无法访问在类中声明的私有成员,编译器行为异常
- 如何从私有成员子类对象捕获异常
- 在初始化成员变量期间有条件地处理异常
- 在构建过程中捕获特定基础成员的异常
- 使用 C++ Boost 的格式对象作为异常成员
- 如果在成员中抛出异常,则删除母对象