C++异常

释放双眼,带上耳机,听听看~!

目录

 

1、异常基本语法

2、栈解旋

3、异常的接口声明

4、异常变量的生命周期

5、异常的多态使用

6、使用系统标准异常

7、编写自己的异常类


1、异常基本语法

  • try 试图执行 try{}中的内容

  • 在可能出现异常的地方 抛出异常  throw

  • try下面 catch捕获异常

  • catch( 捕获类型 )  …代表 所有其他类型

  • 如果不想处理异常,继续向上抛出  throw

  • 如果没有任何处理异常的地方,那么成员调用terminate函数,中断程序

  • 自定义异常类 ,可以抛出自定义的对象  ,捕获自定义的异常


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
1#define _CRT_SECURE_NO_WARNINGS
2#include<iostream>
3using namespace std;
4
5int myDevide(int a, int b)
6{
7   if (b == 0)
8   {
9       //如果b是异常  抛出异常
10      //return - 1;
11      //throw - 1;
12
13      //throw 1;  抛出int类型的异常
14      throw 3.14;  //抛出double类型的异常 异常必须处理,如果不处理就挂掉
15      //throw 'a';
16  }
17  return a / b;
18}
19
20void test01()
21{
22  int a = 10;
23  int b = 0;
24
25  //int ret = myDevide(a, b);  //早期如果返回-1  无法区分到底是结果还是异常
26
27  //C++中异常处理
28
29  try  //尝试
30  {
31      myDevide(a, b);
32  }
33  catch (int)  //捕获异常
34  {
35      cout << "int类型异常捕获" << endl;
36  }
37  catch (double)  //捕获异常
38  {
39      //如果不想处理这个异常 就向上抛出
40      throw;
41      cout << "double类型异常捕获" << endl;
42  }
43  catch (...)
44  {
45      cout << "其他类型异常捕获" << endl;
46  }
47 
48}
49int main(void)
50{
51  try
52  {
53      test01();
54  }
55  catch (char)  //如果异常都没有处理,那么成员terminate函数,使程序中断
56  {
57      cout << "main函数中char异常捕获" << endl;
58  }
59  catch (...)
60  {
61      cout << "main中其他类型异常捕获" << endl;
62  }
63  system("pause");
64  return 0;
65}
66

自定义异常


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
1#define _CRT_SECURE_NO_WARNINGS
2#include<iostream>
3using namespace std;
4
5//自定义异常类
6class myException
7{
8public:
9   void printError()
10  {
11      cout << "自定义异常" << endl;
12  }
13};
14
15int myDevide(int a, int b)
16{
17  if (b == 0)
18  {
19      //如果b是异常  抛出异常
20      //return - 1;
21      //throw - 1;
22
23      //throw 1;  抛出int类型的异常
24      //throw 3.14;  //抛出double类型的异常 异常必须处理,如果不处理就挂掉
25      //throw 'a';
26      throw myException(); //匿名对象
27  }
28  return a / b;
29}
30
31void test01()
32{
33  int a = 10;
34  int b = 0;
35
36  //int ret = myDevide(a, b);  //早期如果返回-1  无法区分到底是结果还是异常
37
38  //C++中异常处理
39
40  try  //常试
41  {
42      myDevide(a, b);
43  }
44  catch (int)  //捕获异常
45  {
46      cout << "int类型异常捕获" << endl;
47  }
48  catch (double)  //捕获异常
49  {
50      //如果不想处理这个异常 就向上抛出
51      throw;
52      cout << "double类型异常捕获" << endl;
53  }
54  catch (myException e)
55  {
56      e.printError();
57  }
58  catch (...)
59  {
60      cout << "其他类型异常捕获" << endl;
61  }
62 
63}
64int main(void)
65{
66  try
67  {
68      test01();
69  }
70  catch (char)  //如果异常都没有处理,那么成员terminate函数,使程序中断
71  {
72      cout << "main函数中char异常捕获" << endl;
73  }
74  catch (...)
75  {
76      cout << "main中其他类型异常捕获" << endl;
77  }
78  system("pause");
79  return 0;
80}
81

2、栈解旋

       异常被抛出后,从进入try块起,到异常被抛掷前,这期间在栈上构造的所有对象,都会被自动析构。析构的顺序与构造的顺序相反,这一过程称为栈的解旋(unwinding)。

  • 从try开始  到 throw 抛出异常之前  所有栈上的对象 都会被释放 这个过程称为栈解旋

  • 栈上对象构造顺序与析构顺序相反


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
1#define _CRT_SECURE_NO_WARNINGS
2#include<iostream>
3using namespace std;
4
5//自定义异常类
6class myException
7{
8public:
9   void printError()
10  {
11      cout << "自定义异常" << endl;
12  }
13};
14
15class Person
16{
17public:
18  Person()
19  {
20      cout << "Person构造" << endl;
21  }
22  ~Person()
23  {
24      cout << "Person析构" << endl;
25  }
26};
27
28int myDevide(int a, int b)
29{
30  if (b == 0)
31  {
32      //如果b是异常  抛出异常
33      //return - 1;
34      //throw - 1;
35
36      //throw 1;  抛出int类型的异常
37      //throw 3.14;  //抛出double类型的异常 异常必须处理,如果不处理就挂掉
38      //throw 'a';
39
40      //栈解旋
41      //从try开始  到throw抛出异常之前  所有栈上的对象 都会被释放 这个过程称为栈解旋
42      //构造和析构顺序相反
43      Person p1;
44      Person p2;
45
46      throw myException(); //匿名对象
47  }
48  return a / b;
49}
50
51
52void test01()
53{
54  int a = 10;
55  int b = 0;
56
57  //int ret = myDevide(a, b);  //早期如果返回-1  无法区分到底是结果还是异常
58
59  //C++中异常处理
60
61  try  //常试
62  {
63      myDevide(a, b);
64  }
65  catch (int)  //捕获异常
66  {
67      cout << "int类型异常捕获" << endl;
68  }
69  catch (double)  //捕获异常
70  {
71      //如果不想处理这个异常 就向上抛出
72      throw;
73      cout << "double类型异常捕获" << endl;
74  }
75  catch (myException e)
76  {
77      e.printError();
78  }
79  catch (...)
80  {
81      cout << "其他类型异常捕获" << endl;
82  }
83 
84}
85int main(void)
86{
87  try
88  {
89      test01();
90  }
91  catch (char)  //如果异常都没有处理,那么成员terminate函数,使程序中断
92  {
93      cout << "main函数中char异常捕获" << endl;
94  }
95  catch (...)
96  {
97      cout << "main中其他类型异常捕获" << endl;
98  }
99  system("pause");
100 return 0;
101}
102

3、异常的接口声明

  • 如果想抛出特定的类型异常 ,可以利用异常的接口声明
  • void func() throw ( int) 只能抛出 int类型
  • throw() 不抛出任何类型异常

4、异常变量的生命周期

  • 如果  MyException e,会多开销一份数据 ,调用拷贝构造

  • 如果 MyExcepiton *e   , 不 new提前释放对象 new 自己管理delete

  • 推荐  MyException &e  容易些 而且 就一份数据


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
1#define _CRT_SECURE_NO_WRNINGS
2#include<iostream>
3using namespace std;
4
5class MyException
6{
7public:
8   MyException()
9   {
10      cout << "MyException默认构造" << endl;
11  }
12  MyException(const MyException & e)
13  {
14      cout << "MyException拷贝构造" << endl;
15  }
16  ~MyException()
17  {
18      cout << "MyException析构" << endl;
19  }
20};
21
22void doWork()
23{
24  throw MyException();
25}
26
27void test01()
28{
29  try
30  {
31      doWork();
32  }
33  catch (MyException &e)  //MyException e 会多开销一份数据,利用引用提高效率
34  {
35      cout << "捕获异常" << endl;
36  }
37}
38int main()
39{
40  test01();
41  system("pause");
42  return 0;
43}
44

MyException e的结果:

C++异常

MyException &e的结果:

C++异常

如果使用指针变量,需要自己delete,否则出现下面的结果

C++异常


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
1#define _CRT_SECURE_NO_WRNINGS
2#include<iostream>
3using namespace std;
4
5class MyException
6{
7public:
8   MyException()
9   {
10      cout << "MyException默认构造" << endl;
11  }
12  MyException(const MyException & e)
13  {
14      cout << "MyException拷贝构造" << endl;
15  }
16  ~MyException()
17  {
18      cout << "MyException析构" << endl;
19  }
20};
21
22void doWork()
23{
24  throw new MyException();
25}
26
27void test01()
28{
29  try
30  {
31      doWork();
32  }
33  catch (MyException *e)  
34  {
35      cout << "捕获异常" << endl;
36      delete e;  //靠自觉 释放对象
37  }
38}
39int main()
40{
41  test01();
42  system("pause");
43  return 0;
44}
45

5、异常的多态使用

  • 利用多态来实现 printError同一个接口调用

  • 抛出不同的错误对象,提示不同错误


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
1#define _CRT_SECURE_NO_WARNINGS
2#include<iostream>
3using namespace std;
4
5//异常基类
6class BaseException
7{
8public:
9   virtual void printError()
10  {
11
12  }
13};
14
15class NullPinterException :public BaseException
16{
17public:
18  virtual void printError()
19  {
20      cout << "空指针异常" << endl;
21  }
22};
23
24class OutofRangeException :public BaseException
25{
26public:
27  virtual void printError()
28  {
29      cout << "越界异常" << endl;
30  }
31};
32
33void doWork()
34{
35  //throw NullPinterException();
36  throw OutofRangeException();
37}
38
39void test01()
40{
41  try
42  {
43      doWork();
44  }
45  catch (BaseException& e)
46  {
47      e.printError();
48  }
49}
50
51
52
53int main()
54{
55  test01();
56  system("pause");
57  return 0;
58}
59

6、使用系统标准异常

  • #incldue <stdexcept>

  • throw out_of_range(”aaa”) 。。。

  • catch(out_of_range & e)  cout  <<  e.what();


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
1#define _CRT_SECURE_NO_WARNINGS
2#include&lt;iostream&gt;
3#include&lt;string&gt;
4using namespace std;
5//系统提供标准异常 要包含头文件
6#include&lt;stdexcept&gt;
7
8class Person
9{
10public:
11  Person(string name, int age)
12  {
13      this-&gt;m_Name = name;
14      //年龄检测
15      if (age&lt;0 || age&gt;200)
16      {
17          //抛出越界异常
18          //throw out_of_range(&quot;年龄越界了!&quot;);
19
20          throw length_error(&quot;长度越界&quot;);
21      }
22  }
23  string m_Name;
24  int m_Age;
25};
26
27void test01()
28{
29  try
30  {
31      Person p(&quot;张三&quot;, 300);
32  }
33  catch (out_of_range &amp;e)
34  {
35      cout &lt;&lt; e.what() &lt;&lt; endl;
36  }
37  catch (length_error &amp;e)
38  {
39      cout &lt;&lt; e.what() &lt;&lt; endl;
40  }
41}
42
43int main()
44{
45  test01();
46  system(&quot;pause&quot;);
47  return 0;
48}
49

7、编写自己的异常类

  • 自己的异常类 需要继承于  exception

  • 重写  虚析构   what()

  • 内部维护以错误信息 字符串

  • 构造时候传入 错误信息字符串,what返回这个字符串

  • string 转 char *   .c_str();


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
1#define _CRT_SECURE_NO_WARNINGS
2#include&lt;iostream&gt;
3using namespace std;
4#include&lt;string&gt;
5using namespace std;
6
7class MyOutOfRangeException :public exception
8{
9public:
10  MyOutOfRangeException(string errorInfo)
11  {
12      this-&gt;m_ErrorInfo = errorInfo;
13  }
14
15  virtual ~MyOutOfRangeException()
16  {
17
18  }
19  virtual const char *  what() const
20  {
21      //返回错误信息
22      //string转char*   +     .c_str()
23      return this-&gt;m_ErrorInfo.c_str();
24  }
25
26  string m_ErrorInfo;
27};
28
29class Person
30{
31public:
32  Person(string name, int age)
33  {
34      this-&gt;m_Name = name;
35
36      //年龄检测
37      if (age&lt;0 || age&gt;200)
38      {
39          //抛出异常
40          throw MyOutOfRangeException(string(&quot;我自己的年龄越界异常&quot;));
41      }
42  }
43
44  string m_Name;
45  int m_Age;
46};
47
48void test01()
49{
50  try
51  {
52      Person p(&quot;zhang&quot;, 300);
53  }
54  catch (MyOutOfRangeException &amp;e)
55  {
56      cout &lt;&lt; e.what();
57  }
58}
59
60int main()
61{
62  test01();
63  system(&quot;pause&quot;);
64  return 0;
65}
66

给TA打赏
共{{data.count}}人
人已打赏
安全技术

Bootstrap 间隔 (Spacing)

2021-12-21 16:36:11

安全技术

从零搭建自己的SpringBoot后台框架(二十三)

2022-1-12 12:36:11

个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索