boost库实用工具之exception
来源:互联网 发布:手机淘宝花呗怎么开通 编辑:程序博客网 时间:2024/06/05 23:40
异常是C++处理错误的重要机制,他改变了传统的使用错误返回值的处理模式,简化了函数的接口和调用代码,有助于编写整洁,优雅,健壮的程序。C++标准库中定义的标准异常类std::exception及其一些子类是整个C++语言处理的基础。 而boost.exception 库针对标准库中异常类的缺陷进行了强化,提供了<<操作符重载,可以向异常传入任意数据,有助于增加异常的信息和表达力,其中部分特性已经加入C++11标准。 exception位于名字空间boost中,为了使用exception,需要包含头文件boost/exception/all.hpp
标准库中的列表
为了使用boost.exception,我们需要先了解c++标准规定的异常体系。
c++标准中定义了一个异常基类std::exception和try/catch/throw异常处理机制,std::exception又派生出若干子类,用以描述不同种类的异常,如bad_alloc, bad_cast, out_or_range等,共同构建了C++异常处理框架。
C++允许任何类型作为异常抛出,但在std::exception出现后,我们应该尽量使用它,因为std::exception提供了一个很有用的函数what(),可以返回异常所携带的信息。
有时我们需要定义自己的错误信息,我们需要继承std::exception及其子类。例如:
class my_exception : public std::logic_error{private: int err_no;//错误信息码public: my_exception(const char* msg, int err): std::logic_error(msg) , err_no(err) { // } int get_err_no() { return err_no; }};
如果系统需要很多不同种类的异常时,这种方法就会成为负担——需要编译异常处理大量代码。
而且这种解决法还存在一个问题:很多时候当异常发生时不能获得有异常的完全诊断信息,而标准库的异常类一旦出现,它就成了一个“死”对象,程序失去了对它的控制能力,只能使用它或者再抛出一个新的异常。
boost.exception针对这些异常定义了新的异常类boost.exception完善了c++的异常处理机制。
类摘要
exception库提供了两个类:exception和error_info,他们是exception库的基础。
exception
class exception{public: exception(); exception(exception const& x); virtual ~exception();private: template<class E,class Tag,class T> friend E const& operator<<(E const&, error_info<Tag, T> const&);};typename value_type* get_error_info(E&x);
注意:它是一个抽象类,几乎没有公开的成员函数。除了它的子类,任何人都不能创建或者销毁它,这保证了exception不被误用。
exception的重要能力在于其友元操作符<<,可以存储error_info对象的信息,存入的信息可以用自由函数get_error_info<>()随时取出来。这个函数返回一个存储数据的指针,如果exception里米有这一种类型的信息返回空。
exception特意没有从std::exception继承。
error_info
class exception{public: exception(); exception(exception const& x); virtual ~exception();private: template<class E,class Tag,class T> friend E const& operator<<(E const&, error_info<Tag, T> const&);};typename value_type* get_error_info(E& x);error_info 提供了向异常类型添加信息的通用解法。第一个模板类型参数Tag是一个标记,他通常(最好)是一个空类,仅用来标记error_info类,使他在模板实例化时生成不同的类型。第二个参数T是真正存储的信息数据,可以用成员函数value()访问
向异常传递信息
exception和error_info被设计为配合std::exception一起工作,自定义的异常类可以安全地从exception和std::exception多重继承,从而获得两者的能力。
注意exception是抽象的,我们必须自己定义它的子类才能使用它,如前所述,exception必须使用虚继承的方式。通常,继承完成后自定义异常类的实现也就完成了,不需要“画蛇添足”地向它增加成员函数或者成员变量。这些都已经由exception完成了。例如:
struct my_excpetion: virtual std::exception,//虚继承,struct 默认public继承 virtual boost::exception // 虚继承,struct 默认public继承{ //空实现,不需要实现代码。};
接下来我们需要定义我们要存储的信息–使用模板类,error_info。用一个struct作为第一个模板参数来标记信息类型,再用第二个模板参数指定信息的数据类型。由于error_info<>的类型定义较长,我们需要用到typedef
例如下面的代码用error_info定义两个存储int和string的信息类:
typedef boost::error_info<struct tag_err_no, int> err_no;typedef boost::error_info<struct tag_err_str, string> err_str;
当异常发生时,我们就可以创建一个自定义的异常类,并用<<操作符来向它存储任意信息,这些信息可以在任何时候用get_error_info()函数获取。
示范代码如下:
struct my_excpetion: virtual std::exception,//虚继承,struct 默认public继承 virtual boost::exception // 虚继承,struct 默认public继承{ //空实现,不需要实现代码。};typedef boost::error_info<struct tag_err_no, int> err_no;typedef boost::error_info<struct tag_err_str, string> err_str;void case1(){ try { try { // 抛出异常,存储信息码 throw my_excpetion() << err_no(10); } catch (my_excpetion& e) { //获取异常内存储的信息 cout << *get_error_info<err_no>(e) << endl; cout << e.what() << endl; e << err_str("other info"); //向异常内追加信息 throw; //然后再次抛出异常 } } catch (my_excpetion& e) // function_try 的捕获代码 { // 获得异常信息 cout << *get_error_info<err_str>(e) << endl; }}
错误信息类
处理异常的一个工作是定义错误类型,我们用typedef来具体化error_info模板类。这通常比较麻烦,exception库特意预定义了若干个定义好的错误信息类
typedef error_info<...> errinfo_api_function;typedef error_info<...> errinfo_at_line;typedef error_info<...> errinfo_errno;typedef error_info<...> errinfo_file_handle;typedef error_info<...> errinfo_file_open_mode;typedef error_info<...> errinfo_type_info_name;
它们可以用于常见的调用API,行号,错误代码,文件handle,文件名等错误信息的处理。例如
try { throw my_excpetion() << errinfo_api_function("call api") << errinfo_errno(10);}catch (boost::exception& e){ cout << *get_error_info<errinfo_api_function>(e); cout << *get_error_info<errinfo_errno>(e);}
另外,exception库还提供了三个预定义的错误信息类型,但命名规则略有不同:
typedef error_info<…> throw_function;
typedef error_info<…> throw_file;
typedef error_info<…> throw_line;
这三个错误信息类,主要用于存储源代码的信息,配合宏BOOST_CURRENT_FUNCTION,FILE和LINE使用,可以获取函数名,源文件名和源代码行号。
如果这些预定义的还不能满足要求,我们还需要用typedef来定义我们错误信息。
可以用宏DEFINE_ERROR_INFO。
#define DEFINE_ERROR_INFO(type, name) \ typedef boost::error_info<struct tag_##name, type> nameDEFINE_ERROR_INFO<int,err_no>; 就相当于typedef boost::error_info<struct tag_err_no,int >err_no
包装标准异常
exception库提供了一个模板函数enable_error_info(T& e), 其中T是标准异常类或者其他自定义类型。它可以包装类型T,产生从boost::exception和T派生的类,从而不修改原异常处理体系的前提下获得boost::exception的所有好处。如果类型T已经是boost::exception的子类,那么enable_error_info将返回e的一个拷贝。
enable_error_info()通常在程序中已经存在异常类的场合,对这些异常类的修改很困难甚至不可能(比如已经编译成库)。这时候enable_error_info()就可以包装原有的异常类,从而很容易的在不改变原有代码的基础上把boost::exception集成到原有的异常体系中去。
//自定义的一个异常类,未使用boost::exceptionstruct my_err{};void cast2(){ try { //使用enable_error_info包装自定义的异常 throw enable_error_info(my_err()) << errinfo_errno(10); throw enable_error_info(std::runtime_error("runtime")) << errinfo_at_line(__LINE__); } catch (boost::exception& e)//这里必须使用errinfo_errno(10)来捕获 { cout << *get_error_info<errinfo_errno>(e) << endl; }}
使用函数抛出异常
exception库在头文件
- boost库实用工具之exception
- boost 库实用工具之optional
- boost库实用工具之assign
- boost实用工具之tribool库
- Boost库学习笔记-----------实用工具之禁止复制 noncopyable
- Boost实用工具
- boost 实用工具
- Boost 库中的实用工具类使用入门
- Boost 库中的实用工具类使用入门
- Boost 库中的实用工具类使用入门
- Boost 库中的实用工具类使用入门
- Boost 库中的实用工具类使用入门
- Boost 库中的实用工具类使用入门
- Boost 库中的实用工具类使用入门
- Boost 库中的实用工具类使用入门
- Boost 库中的实用工具类使用入门
- Boost库中的实用工具类使用入门
- Boost 库中的实用工具类使用入门
- 转 别人的
- Spring笔记二
- 使用HttpURLConnection
- #bzoj2932#【重庆市NOIP模拟赛】旅行(贪心 DP是不可以的!)
- template(name="remote" type="string" string="%msg%")
- boost库实用工具之exception
- Android 发布项目到私服Nexus仓库
- js 格式化金额
- antd源码解析(一)button控件的解析
- js定时动态增加列表
- BigDecimal加减乘除运算
- 自定义view实现多点触控
- mybatis常用jdbcType数据类型以及对应的JavaType
- [BZOJ2239]猜谜语