Chinaunix首页 | 论坛 | 博客
  • 博客访问: 487534
  • 博文数量: 80
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 1916
  • 用 户 组: 普通用户
  • 注册时间: 2013-07-11 22:01
个人简介

从事实时计算多年,熟悉jstorm/spark/flink/kafka/rocketMq, 热衷于开源,希望在这里和前辈们一起学习与分享,得到长足的进步!邮箱:hustfxj@gmail.com 我的githup地址是:https://github.com/hustfxj。欢迎和大家一起交流探讨问题。

文章分类

全部博文(80)

文章存档

2017年(11)

2015年(3)

2014年(33)

2013年(33)

分类: C/C++

2013-09-14 13:43:50

 

C++语言本身或标准程序库所抛出的所有异常,都派生自基类exception。这是其他数个标准异常类别的基类,它们共同构成一个类体系:

图一 标准异常阶层体系

这些标准异常类别分为三组:

1)语言本身所支持的异常

此类异常用以支撑某些语言特性。主要包括:
bad_alloc
new操作失败会抛出。
bad_cast
:执行期间加在一个引用上面的动态性型别转换操作失败时抛出。
bad_typeid
:执行RTTI时,交给typeid的参数为零或空指针时抛出
bad_exception
:非预期的异常

2C++标准程序库发出的异常

总是派生自logic_error。逻辑错误是由于程序内部逻辑而导致的错误。逻辑错误是可以避免的,且在程序开始执行之前,能够被检测到。
C++
标准库中定义的逻辑错误如下:

[cpp] view plaincopyprint?

1.       class logic_error : public exception {  

2.       public:  

3.         explicit logic_error (const string& what_arg);  

4.       };  

5.         

6.       class invalid_argument : public logic_error {  

7.       public:  

8.         explicit invalid_argument (const string& what_arg);  

9.       };  

10.     

11.   class out_of_range : public logic_error {  

12.   public:  

13.     explicit out_of_range (const string& what_arg);  

14.   };  

15.     

16.   class length_error : public logic_error {  

17.   public:  

18.     explicit length_error (const string& what_arg);  

19.   };  

20.     

21.   class domain_error : public logic_error {  

22.   public:  

23.     explicit domain_error (const string& what_arg);  

24.   }; class logic_error : public exception {public:  explicit logic_error (const string& what_arg);

};

class invalid_argument : public logic_error {

public:

  explicit invalid_argument (const string& what_arg);

};

class out_of_range : public logic_error {

public:

  explicit out_of_range (const string& what_arg);

};

class length_error : public logic_error {

public:

  explicit length_error (const string& what_arg);

};

class domain_error : public logic_error {

public:

  explicit domain_error (const string& what_arg);

};

错误分类解释及举例:

domain_error:专业领域内的范畴 

invalid_argument:无效参数,比如讲bitsetchar而非01进行初始化

length_error:可能超越了最大极限,比如对着某个字符串附加太多字符。 

out_of_range:参数不再预期范围内。例如在诸如array的容器或字符串string中采用一个错误索引。

3)程序作用域之外发出的异常

总是派生自runtime_error,用来指出不在程序范围内,且不容易回避的事件。此类错误只在程序执行时才是可检测的。C++标准库中的定义如下:

[cpp] view plaincopyprint?

1.       class runtime_error : public exception {  

2.       public:  

3.         explicit runtime_error (const string& what_arg);  

4.       };  

5.         

6.       class range_error : public runtime_error {  

7.       public:  

8.         explicit range_error (const string& what_arg);  

9.       };  

10.     

11.   class overflow_error : public runtime_error {  

12.   public:  

13.     explicit overflow_error (const string& what_arg);  

14.   };  

15.     

16.   class underflow_error : public runtime_error {  

17.   public:  

18.     explicit underflow_error (const string& what_arg);  

19.   };  class runtime_error : public exception {

public:

  explicit runtime_error (const string& what_arg);

};

class range_error : public runtime_error {

public:

  explicit range_error (const string& what_arg);

};

class overflow_error : public runtime_error {

public:

  explicit overflow_error (const string& what_arg);

};

class underflow_error : public runtime_error {

public:

  explicit underflow_error (const string& what_arg);

};

range_error:内部计算时发生区间错误

overflow_error:算数运算时发生上溢

underflow_error:算数运算时发生下溢
实例代码:

[cpp] view plaincopyprint?

1.       #include   

2.       #include    

3.       #include    

4.       #include    

5.       #include    

6.       #include    

7.         

8.       using namespace std;  

9.         

10.   //自定义配置器,vector分配空间使用   

11.   template  

12.   class stingyallocator : public allocator<_Ty>  

13.   {  

14.   public:  

15.      template   

16.       struct rebind {  

17.             typedef stingyallocator other;  

18.       };  

19.     

20.      size_t max_size( ) const  

21.      {  

22.            return 10;  

23.      };  

24.   };  

25.     

26.   int main()  

27.   {  

28.       //逻辑错误:out_of_range   

29.       try {  

30.         string str( "Micro" );  

31.         string rstr( "soft" );  

32.         str.append( rstr, 5, 3 );  

33.         cout << str << endl;  

34.      }  

35.      catch ( exception &e ) {  

36.         cerr << "Caught: " << e.what( ) << endl;  

37.         cerr << "Type: " << typeid( e ).name( ) << endl << endl;  

38.      };  

39.     

40.      //逻辑错误:length_error   

41.      try  

42.      {  

43.         vector<int, stingyallocator< int > > myv;  

44.         for ( int i = 0; i < 11; i++ )  

45.           myv.push_back( i );  

46.      }  

47.      catch ( exception &e )  

48.      {  

49.         cerr << "Caught " << e.what( ) << endl;  

50.         cerr << "Type " << typeid( e ).name( ) << endl << endl;  

51.      };  

52.     

53.      //逻辑错误:invalid_argument   

54.      try  

55.      {  

56.         bitset< 32 > bitset( string( "11001010101100001b100101010110000") );  

57.      }  

58.      catch ( exception &e )  

59.      {  

60.         cerr << "Caught " << e.what( ) << endl;  

61.         cerr << "Type " << typeid( e ).name( ) << endl << endl;  

62.      };  

63.     

64.      //逻辑错误:domain_error   

65.      try  

66.      {  

67.         throw domain_error( "Your domain is in error!" );  

68.      }  

69.      catch (exception &e)  

70.      {  

71.         cerr << "Caught: " << e.what( ) << endl;  

72.         cerr << "Type: " << typeid(e).name( ) << endl << endl;  

73.      };  

74.     

75.      //运行时错误:range_error   

76.       try  

77.      {  

78.         throw range_error( "The range is in error!" );  

79.      }  

80.      catch (exception &e)  

81.      {  

82.         cerr << "Caught: " << e.what( ) << endl;  

83.         cerr << "Type: " << typeid( e ).name( ) << endl << endl << endl;  

84.      };  

85.     

86.      //运行时错误:underflow_error   

87.      try  

88.      {  

89.         throw underflow_error( "The number's a bit small, captain!" );  

90.      }  

91.      catch ( exception &e ) {  

92.         cerr << "Caught: " << e.what( ) << endl;  

93.         cerr << "Type: " << typeid( e ).name( ) << endl << endl;  

94.      };  

95.     

96.       //运行时错误:overflow_error   

97.       try  

98.       {  

99.           bitset< 33 > bitset;  

100.                    bitset[32] = 1;  

101.                    bitset[0] = 1;  

102.                    unsigned long x = bitset.to_ulong( );  

103.                }  

104.                catch(exception &e)  

105.                {  

106.                    cerr << "Caught " << e.what() << endl;  

107.                    cerr << "Type: " << typeid(e).name() << endl << endl;  

108.                }  

109.              

110.                return 0;  

111.            }  

#include

#include

#include

#include

#include

#include

using namespace std;

//自定义配置器,vector分配空间使用

template

class stingyallocator : public allocator<_Ty>

{

public:

   template

    struct rebind {

          typedef stingyallocator other;

    };

   size_t max_size( ) const

   {

         return 10;

   };

};

int main()

{

    //逻辑错误:out_of_range

    try {

      string str( "Micro" );

      string rstr( "soft" );

      str.append( rstr, 5, 3 );

      cout << str << endl;

   }

   catch ( exception &e ) {

      cerr << "Caught: " << e.what( ) << endl;

      cerr << "Type: " << typeid( e ).name( ) << endl << endl;

   };

   //逻辑错误:length_error

   try

   {

      vector > myv;

      for ( int i = 0; i < 11; i++ )

        myv.push_back( i );

   }

   catch ( exception &e )

   {

      cerr << "Caught " << e.what( ) << endl;

      cerr << "Type " << typeid( e ).name( ) << endl << endl;

   };

   //逻辑错误:invalid_argument

   try

   {

      bitset< 32 > bitset( string( "11001010101100001b100101010110000") );

   }

   catch ( exception &e )

   {

      cerr << "Caught " << e.what( ) << endl;

      cerr << "Type " << typeid( e ).name( ) << endl << endl;

   };

   //逻辑错误:domain_error

   try

   {

      throw domain_error( "Your domain is in error!" );

   }

   catch (exception &e)

   {

      cerr << "Caught: " << e.what( ) << endl;

      cerr << "Type: " << typeid(e).name( ) << endl << endl;

   };

   //运行时错误:range_error

    try

   {

      throw range_error( "The range is in error!" );

   }

   catch (exception &e)

   {

      cerr << "Caught: " << e.what( ) << endl;

      cerr << "Type: " << typeid( e ).name( ) << endl << endl << endl;

   };

   //运行时错误:underflow_error

   try

   {

      throw underflow_error( "The number's a bit small, captain!" );

   }

   catch ( exception &e ) {

      cerr << "Caught: " << e.what( ) << endl;

      cerr << "Type: " << typeid( e ).name( ) << endl << endl;

   };

    //运行时错误:overflow_error

    try

    {

        bitset< 33 > bitset;

        bitset[32] = 1;

        bitset[0] = 1;

        unsigned long x = bitset.to_ulong( );

    }

    catch(exception &e)

    {

        cerr << "Caught " << e.what() << endl;

        cerr << "Type: " << typeid(e).name() << endl << endl;

    }

    return 0;

}

运行结果(CodeBlocks):

参考资料: 

C++中异常类的使用方法



常见的异常处理问题

动态内存分配错误

         ① 分配动态内存使用的是newnew[]操作符,如果他们分配内存失败,就会抛出bad_alloc异常,在new头文件中,所以我们的代码中应该捕捉这些异常。常见的代码形式如下:

[cpp] view plaincopyprint?

1.  try {  

2.      //其他代码   

3.      ptr = new int[num_max];  

4.      //其他代码   

5.  catch(bad_alloc &e) {  

6.      //这里常见的处理方式为:先释放已经分配的内存,然后结束程序,或者打印一条错误信息并继续执行   

7.  }  

try {
    //其他代码
    ptr = new int[num_max];
    //其他代码
} catch(bad_alloc &e) {
    //这里常见的处理方式为:先释放已经分配的内存,然后结束程序,或者打印一条错误信息并继续执行
}

         ② 可以使用类似C语言的方式处理,但这时要使用的nothrow版本,使用"new (nothrow)"的形式分配内存。这时,如果分配不成功,返回的是NULL指针,而不再是抛出bad_alloc异常。
        
③ 可以定制内存分配失败行为C++允许指定一个new 处理程序(newhandler)回调函数。默认的并没有new 处理程序,如果我们设置了new 处理程序,那么当newnew[] 分配内存失败时,会调用我们设定的new 处理程序,而不是直接抛出异常。通过set_new_handler函数来设置该回调函数。要求被回调的函数没有返回值,也没有形式参数

        注意事项:(以前学java的尤其要注意,和java中不太一样)

                ① 如果函数没有显式的声明 抛出列表,表示异常可以抛出任意列表。(在java中,如果没有异常抛出列表,那么是不能抛出任何异常的)。

                C++的 “throw()”相当于java不声明抛出列表。都表示不抛出任何异常。

                ③ 在C++中,编译的时候,编译器不会对异常抛出列表进行检查。也就是说,如果你声明了抛出列表,即使你的函数代码中抛出了没有在抛出列表中指定的异常,你的程序依然可以通过编译,到运行时才会出错,对于这样的异常,在C++中称为“意外异常”(unexpeced exception)。(这点和java又不相同,在java中,是要进行严格的检查的)。

阅读(2090) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~