c++异常处理

C++ 异常处理

C++ 异常处理涉及到三个关键字:try、catch、throw

  • throw: 当问题出现时,程序会抛出一个异常。这是通过使用 throw 关键字来完成的。
  • catch: 在您想要处理问题的地方,通过异常处理程序捕获异常。catch 关键字用于捕获异常。
  • try: try 块中的代码标识将被激活的特定异常。它后面通常跟着一个或多个 catch 块。
  • 如果有一个块抛出一个异常,捕获异常的方法会使用 try 和 catch 关键字。try 块中放置可能抛出异常的代码,try 块中的代码被称为保护代码。
1
2
3
4
5
6
7
8
9
10
11
12
13
try
{
// 保护代码
}catch( ExceptionName e1 )
{
// catch 块
}catch( ExceptionName e2 )
{
// catch 块
}catch( ExceptionName eN )
{
// catch 块
}

如果 try 块在不同的情境下会抛出不同的异常,这个时候可以尝试罗列多个 catch 语句,用于捕获不同类型的异常。

抛出异常

您可以使用 throw 语句在代码块中的任何地方抛出异常。throw 语句的操作数可以是任意的表达式,表达式的结果的类型决定了抛出的异常的类型。

以下是尝试除以零时抛出异常的实例:

1
2
3
4
5
6
7
8
double division(int a, int b)
{
if( b == 0 )
{
throw "Division by zero condition!";
}
return (a/b);
}

捕获异常

catch 块跟在 try 块后面,用于捕获异常。您可以指定想要捕捉的异常类型,这是由 catch 关键字后的括号内的异常声明决定的。

1
2
3
4
5
6
7
try
{
// 保护代码
}catch( ExceptionName e )
{
// 处理 ExceptionName 异常的代码
}

上面的代码会捕获一个类型为 ExceptionName 的异常。如果您想让 catch 块能够处理 try 块抛出的任何类型的异常,则必须在异常声明的括号内使用省略号 …,如下所示:

1
2
3
4
5
6
7
try
{
// 保护代码
}catch(...)
{
// 能处理任何异常的代码
}
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
#include <iostream>
using namespace std;

double division(int a, int b)
{
if( b == 0 )
{
throw "Division by zero condition!";
}
return (a/b);
}

int main ()
{
int x = 50;
int y = 0;
double z = 0;

try {
z = division(x, y);
cout << z << endl;
}catch (const char* msg) {
cerr << msg << endl;
}

return 0;
}

由于我们抛出了一个类型为 const char 的异常,因此,当捕获该异常时,我们必须在 catch 块中使用 const char。当上面的代码被编译和执行时,它会产生下列结果:

Division by zero condition!

C++ 标准的异常

C++ 提供了一系列标准的异常,我们可以在程序中使用这些标准的异常。它们是以父子类层次结构组织起来的。

两个异常相关库分别是:

1
2
#include <stdexcept>
#include <exception>

定义新的异常

您可以通过继承和重载 exception 类来定义新的异常。下面的实例演示了如何使用 std::exception 类来实现自己的异常:

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
#include <iostream>
#include <exception>
using namespace std;

struct MyException : public exception
{
const char * what () const throw ()
{
return "C++ Exception";
}
};

int main()
{
try
{
throw MyException();
}
catch(MyException& e)
{
std::cout << "MyException caught" << std::endl;
std::cout << e.what() << std::endl;
}
catch(std::exception& e)
{
//其他的错误
}
}
1
2
3
4
5
这将产生以下结果:

MyException caught
C++ Exception
在这里,what() 是异常类提供的一个公共方法,它已被所有子异常类重载。这将返回异常产生的原因。

exception和stdexcept中定义的异常类:

stdexcept:

logic_error:

1

runtime_error:

1

exception:

1

应用:

编写一个矩阵类,在进行加法运算和查找元素时候能提供异常检查,并在规格不符时候抛出系统自带的或自定义的异常。

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
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
#include <vector> 
#include <stdexcept>
#include <iostream>
using namespace std;

class Matrix
{
private:
int rows;
int columns;
vector<double> elements;

public:
Matrix(int rows, int columns) {
this->rows = rows;
this->columns = columns;
for (int i = 0; i < rows * columns; ++ i) {
elements.push_back(0.0);
}
}

int size(int dimension) const {
switch (dimension) {
case 1: return rows;
case 2: return columns;
}
return 0;
}

double get(int row, int column) const;

void set(int row, int column, double value);

Matrix operator + (const Matrix & matrix2) const;
};


class MatrixSizesDoNotMatchException{

};

double Matrix::get(int row, int column) const{
if(row > this->rows || column > this->columns || row <= 0 || column <= 0)
throw out_of_range("Index out of bound");
return this->elements[(row-1)*this->columns+column-1];
}

void Matrix::set(int row, int column, double value){
if(row > this->rows || column > this->columns || row <= 0 || column <= 0)
throw out_of_range("Index out of bound");
this->elements[(row-1)*this->columns+column-1] = value;
}

Matrix Matrix::operator +(const Matrix& matrix2) const{
if((this->rows != matrix2.rows) || (this->columns != matrix2.columns))
throw MatrixSizesDoNotMatchException();
Matrix ret(this->rows, this->columns);
for(int i=0; i<this->rows*this->columns; i++)
ret.elements[i] = this->elements[i]+matrix2.elements[i];
return ret;
}

Matrix read() {
int rows;
int columns;
cin >> rows >> columns;
Matrix matrix(rows, columns);
for (int i = 0; i < rows; ++ i) {
for (int j = 0; j < columns; ++ j) {
double value;
cin >> value;
matrix.set(i + 1, j + 1, value);
}
}
return matrix;
}

void print(const Matrix & matrix) {
int rows = matrix.size(1);
int columns = matrix.size(2);
cout << "(" << rows << "," << columns << ")" << endl;
for (int i = 0; i < rows; ++ i) {
for (int j = 0; j < columns; ++ j) {
cout << " " << matrix.get(i + 1, j + 1);
}
cout << endl;
}
}

void test1(const Matrix & matrix) {
for (int i = 0; i < 2; ++ i) {
int row;
int column;
cin >> row >> column;
try {
double value = matrix.get(row, column);
cout << "value = " << value << endl;
}
catch (out_of_range & ex) {
cout << "caught: out_of_range" << endl;
}
}
}

void test2(const Matrix & matrix) {
for (int i = 0; i < 2; ++ i) {
Matrix matrix2 = read();
try {
matrix2 = matrix + matrix2;
print(matrix2);
}
catch (MatrixSizesDoNotMatchException & ex) {
cout << "caught: MatrixSizesDoNotMatchException" << endl;
}
}
}

int main() {
Matrix matrix = read();
test1(matrix);
test2(matrix);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
EXAMPLE INPUT
2 3
1 2 3
4 5 6

1 2
2 4

2 3
2 3 4
3 4 5

2 4
1 2 3 4
4 3 2 1
EXAMPLE OUTPUT
value = 2
caught: out_of_range
(2,3)
3 5 7
7 9 11
caught: MatrixSizesDoNotMatchException
Donate? comment?