设为首页 加入收藏

TOP

4.9.4 更进一步的用法
2013-10-07 15:01:02 来源: 作者: 【 】 浏览:69
Tags:4.9.4 更进一步 用法

4.9.4  更进一步的用法

通过例子我们基本了解了exception的用法,可以看到exception的使用是相当清晰简单的,同时又提供了灵活强大的功能,使异常类有了更多的用途。

由于从exception派生的异常类定义非常简单,没有实现代码,因此,可以很容易地建立起一个适合自己程序的、精细完整的异常类体系,使每个异常类只对应一种错误类型。只要都使用虚继承,类体系可以任意复杂,充分表达错误的含义。

处理异常的另一个重要工作是定义错误信息类型,基本方法是使用typedef来具体化error_info模板类。这通常比较麻烦,特别是有大量信息类型的时候。因此exception库特意提供若干预先定义好的错误信息类,如同标准库定义的logic_err等类型,使程序员用起来更轻松:

  1. typedef error_info<struct errinfo_api_function_,char const *> 
  2.  errinfo_api_function;  
  3. typedef error_info<struct errinfo_at_line_,int> errinfo_at_line;  
  4. typedef error_info<struct errinfo_errno_,int> errinfo_errno;  
  5. typedef error_info<struct errinfo_file_handle_,weak_ptr<FILE> > 
  6.  errinfo_file_handle;  
  7. typedef error_info<struct errinfo_file_name_,std::string> errinfo_file_name;  
  8. typedef error_info<struct errinfo_file_open_mode_,std::string> 
  9. errinfo_file_open_mode;  
  10. typedef error_info<struct errinfo_type_info_name_,std::string> 
  11.  errinfo_type_info_name;  

它们可以用于常见的调用API、行号、错误代码、文件handle、文件名等错误信息的处理。例如:
  1. try  
  2. {  
  3.     throw my_exception() << errinfo_api_function("call api")  
  4.             << errinfo_errno(101);  
  5. }  
  6. catch (boost::exception& e)  
  7. {  
  8.     cout << *get_error_info<errinfo_api_function>(e);  
  9.     cout << *get_error_info<errinfo_errno>(e);  
  10. }  

另外,exception库还提供三个预定义错误信息类型,但命名规则略有不同:
  1. typedef error_info<struct throw_function_,char const *> throw_function;  
  2. typedef error_info<struct throw_file_,char const *> throw_file;  
  3. typedef error_info<struct throw_line_,int> throw_line;  

这三个错误信息类型主要用于存储源代码的信息,配合宏BOOST_CURRENT_FUNCTION(参见4.12.2节,第158页)、__FILE__和__LINE__使用,可以获得调用函数名、源文件名和源代码行号。

但如果这些预定义类不能满足要求,我们还要再使用typedef。为解决这个不大不小的麻烦,我们可以自定义一个辅助工具宏DEFINE_ERROR_INFO,它可以方便快捷地实现error_info的定义:

  1. #define DEFINE_ERROR_INFO(type, name) \  
  2.     typedef boost::error_info<struct tag_##name, type> name  

宏DEFINE_ERROR_INFO接受两个参数,type是它要存储的类型,name是所需要的错误信息类型名,使用预处理命令##创建了error_info所需要的标签类。它的使用方法很简单,就像是声明一个变量:
  1. DEFINE_ERROR_INFO(int, err_no); 

在宏展开后它相当于:
  1. typedef boost::error_info<struct tag_err_no, int> err_no; 

如果你担心tag_前缀太简单,可能会与其他类名发生冲突(通常几率很小),也可以自己定制特殊的标记字符串,比如采用公司名+团队名的方式。但如果这两者发生变化(公司改制、团队合并等),标记的含义就会变得难以维护。本书建议用内置的__FILE__和__LINE__宏,像这样:
  1. tag_##__FILE__##__LINE__##name 

这几乎不会造成任何可能的冲突。
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇4.9.6 使用函数抛出异常 下一篇4.9.7 获得更多的调试信息

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: