1. 异常处理的概念
在编写程序时,由于各种各样的原因会出现错误,比如输入数据不符合要求、访问不存在的文件等。这些错误如果不加处理,可能会导致程序崩溃或者产生意想不到的结果。因此,在程序中加入异常处理机制,可以使程序在出现错误时能够优雅地退出或者采取相应的措施进行处理。
异常处理机制就是指在程序中特意设置用于处理错误的代码模块,称为异常处理程序或异常处理块,在程序出现问题时,将控制权转移到这个程序中进行处理。
一般情况下,程序中嵌入了很多可以抛出异常的函数,如果函数在执行时出现错误,就会抛出异常。抛出异常的函数需要向调用函数传递错误信息,调用函数需要做出响应,这样,异常便会一级一级地传递到顶层函数。
异常处理机制提供了一种将错误信息传递到高层函数的方法,高层函数可以选择继续传递异常信息或者进行处理。
2. c++中的异常处理机制
2.1 c++中的异常类型
2.1 c++中的异常类型
c++中提供了一些常见的异常类型,程序员可以使用这些异常类型或者自定义异常类型来抛出异常。
常见的c++异常类型包括:
std::exception,是所有标准异常的父类。
std::runtime_error,表示运行时错误。
std::logic_error,表示逻辑错误。
std::bad_alloc,表示内存分配失败。
std::bad_cast,表示类型转换失败。
std::range_error,表示范围错误,如下标越界。
std::overflow_error,表示溢出错误。
std::underflow_error,表示欠流错误。
2.2 抛出异常
c++中抛出异常可以使用关键字throw
,并且需要跟上一个异常对象或者一个类对象的引用。
假设我们有一个函数,需要接收一个整数参数,如果这个整数为负数,就抛出一个异常。
void func(int num){
if(num < 0){
throw std::runtime_error("num is negative");
}
}
上述代码中,std::runtime_error
表示抛出一个运行时错误异常,包含错误信息"num is negative"
。
2.3 捕获异常
c++中使用try-catch
块来捕获异常,如果try
块中的代码抛出了异常,则控制流会进入catch
块,执行相应的处理。
假设我们在一个函数中调用了func
函数,需要在try
块中调用这个函数,并且在catch
块中捕获并处理异常。
void foo(int num){
try{
func(num);
} catch(std::exception & e){
std::cerr << e.what() << std::endl;
}
}
上述代码中,try
块中调用了func
函数,如果func
函数抛出了异常,则catch
块中的代码会被执行。在catch
块中,我们使用e.what()
函数来获取异常的错误信息并输出。
3. c++异常处理的实例
下面我们来举一个实际的例子,详细介绍如何在c++中使用异常处理机制。
3.1 例子介绍
假设我们需要编写一个程序用于处理矩阵,要求实现以下功能:
能够输入矩阵的行和列,并且自动分配内存。
能够将矩阵中的某个元素设置为指定值。
能够获取矩阵中指定位置的元素。
在实现以上功能时,需要考虑异常情况,如输入的矩阵维数不符合要求,访问不存在的元素等问题。因此,在编写程序时需要使用异常处理机制。
3.2 代码实现
首先,我们定义一个矩阵类Matrix
,包含以下成员函数:
Matrix(int row, int col)
,构造函数,用于输入矩阵的行和列,并且分配内存。
~Matrix()
,析构函数,用于释放内存。
void set(int row, int col, double val)
,用于将某个元素设置为指定的值。
double get(int row, int col)
,用于获取矩阵中指定位置的元素。
下面是Matrix
类的实现代码:
class Matrix{
public:
Matrix(int row, int col){
if(row <= 0 || col <= 0){
throw std::runtime_error("invalid matrix dimension");
}
m_row = row;
m_col = col;
m_data = new double*[row];
for(int i = 0; i < row; i++){
m_data[i] = new double[col];
}
}
~Matrix(){
for(int i = 0; i < m_row; i++){
delete[] m_data[i];
}
delete[] m_data;
}
void set(int row, int col, double val){
if(row < 0 || row >= m_row || col < 0 || col >= m_col){
throw std::runtime_error("invalid matrix index");
}
m_data[row][col] = val;
}
double get(int row, int col){
if(row < 0 || row >= m_row || col < 0 || col >= m_col){
throw std::runtime_error("invalid matrix index");
}
return m_data[row][col];
}
private:
int m_row;
int m_col;
double ** m_data;
};
在Matrix
类中,我们使用了异常处理机制来处理矩阵中的错误情形,在set
和get
函数中,首先判断输入的行和列是否超出矩阵范围,如果超出范围,则抛出异常。
下面是使用Matrix
类的主函数代码:
int main(){
int row, col;
std::cout << "input matrix dimension: ";
std::cin >> row >> col;
Matrix m(row, col);
std::cout << "input matrix elements: " << std::endl;
for(int i = 0; i < row; i++){
for(int j = 0; j < col; j++){
double val;
std::cin >> val;
m.set(i, j, val);
}
}
std::cout << "input element index: ";
int r, c;
std::cin >> r >> c;
try{
double val = m.get(r, c);
std::cout << "element value: " << val << std::endl;
} catch(std::exception & e){
std::cerr << e.what() << std::endl;
}
return 0;
}
在主函数中,我们首先输入矩阵的行和列,然后创建一个Matrix
对象。接着,我们使用set
函数输入矩阵元素,注意在输入时需要使用try-catch
块来捕获可能的异常。最后,我们输入要获取的元素的行和列,并使用get
函数获取该元素的值,同样需要使用try-catch
块来捕获可能的异常。
3.3 执行结果
我们在控制台输入以下命令:
input matrix dimension: 2 3
input matrix elements:
1.0 2.0 3.0
4.0 -5.0 6.0
input element index: 2 1
运行结果如下:
invalid matrix index
可以看到,在输入要获取的元素位置时,由于输入的行数超出了矩阵的范围,因此程序抛出了异常并在catch
块中输出了错误信息。
4. 总结
异常处理机制是现代编程语言中非常重要的一部分。c++在设计时充分考虑了异常处理机制的实现,提供了非常方便和实用的异常处理语法和类型。在c++中,我们可以自定义异常类型,并使用try-catch块来捕获和处理异常情况,从而使程序更加健壮和容错。