目录
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的结果:
MyException &e的结果:
如果使用指针变量,需要自己delete,否则出现下面的结果
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<iostream>
3#include<string>
4using namespace std;
5//系统提供标准异常 要包含头文件
6#include<stdexcept>
7
8class Person
9{
10public:
11 Person(string name, int age)
12 {
13 this->m_Name = name;
14 //年龄检测
15 if (age<0 || age>200)
16 {
17 //抛出越界异常
18 //throw out_of_range("年龄越界了!");
19
20 throw length_error("长度越界");
21 }
22 }
23 string m_Name;
24 int m_Age;
25};
26
27void test01()
28{
29 try
30 {
31 Person p("张三", 300);
32 }
33 catch (out_of_range &e)
34 {
35 cout << e.what() << endl;
36 }
37 catch (length_error &e)
38 {
39 cout << e.what() << endl;
40 }
41}
42
43int main()
44{
45 test01();
46 system("pause");
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<iostream>
3using namespace std;
4#include<string>
5using namespace std;
6
7class MyOutOfRangeException :public exception
8{
9public:
10 MyOutOfRangeException(string errorInfo)
11 {
12 this->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->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->m_Name = name;
35
36 //年龄检测
37 if (age<0 || age>200)
38 {
39 //抛出异常
40 throw MyOutOfRangeException(string("我自己的年龄越界异常"));
41 }
42 }
43
44 string m_Name;
45 int m_Age;
46};
47
48void test01()
49{
50 try
51 {
52 Person p("zhang", 300);
53 }
54 catch (MyOutOfRangeException &e)
55 {
56 cout << e.what();
57 }
58}
59
60int main()
61{
62 test01();
63 system("pause");
64 return 0;
65}
66