使用形式如下:
try //使用try标识下面代码段抛出的异常将会由catch语句处理
{
throw "some error occur"; //使用throw抛出异常
}
catch (const char* e) //catch 语句匹配异常的数据类型,并执行对应处理
{
std::cout << e <<std::endl; //此处输出:some error occur
}
catch (int) //可有多个catch匹配不同类型的错误;形参名(如上面的e)可省略
{
}
try
try
顾名思义就是要尝试执行下面的语句,如果有抛出错误可以通过catch
来处理。没有try
就无法用catch
。
throw
throw
代表抛出异常,其后面可以跟随各种内置或自定义类型,如果是自定义的类要确保其复制/移动构造函数和析构函数可以访问,因为异常处理过程中会发生对象的复制或移动。
除了直接在try
语句块中throw
外,调用的函数内也可以throw
。如:
int divide(int x, int y)
{
if (y == 0) throw "divide 0 error";
return x / y;
}
int main()
{
try
{
divide(1, 0); // try中调用函数,函数内throw
}
catch (const char* e)
{
std::cout << e <<std::endl; // 此处输出:divide 0 error
}
}
C++ 在throw
后会一直向函数上层寻找try catch
,若到main
之后还没找到就会中断程序。
若不希望函数向上抛出异常,可以在函数的声明和定义中增加noexcept
关键字,如void func() noexcept
,这会阻断异常传播,转而直接调用std::terminate
终止程序。增加此关键词也可以使得编译器做更多优化。
这套异常机制也只能处理手动throw
出来的错误,对于原有的段错误、除0错误之类还会像原来一样直接终止程序。需要自己像上面的divide
函数那样添加检查和抛出的逻辑。不过标准库中已经实现了很多相关的抛出逻辑了。
catch
当try
里throw
异常后,程序会从上到下挨个尝试匹配catch
语句中的错误类型,匹配成功则执行其中的代码并不再执行后续的catch
语句。
匹配成功主要的标准是:
catch
中的类型与抛出的异常类型相同catch
中类型是抛出的异常类型的父类
在该标准的基础上,允许catch
中增加额外的const
或volatile
修饰(但不允许减少修饰);允许catch
中使用引用。
除此之外可以用catch(...)
匹配任意类型。
举例来说,下面的几个catch
都可以匹配成功:
struct A // 定义父类
{
};
struct B: public A // 定义子类
{
};
int main()
{
try
{
B b;
throw b;
}
catch (const A& e) // 父类引用捕获
{
std::cout << "Base's reference" <<std::endl;
}
catch (volatile B e) // 子类捕获
{
std::cout << "Same class" << std::endl;
}
catch (...) // 全捕获
{
std::cout << "All exception"<< std::endl;
}
return 0;
}
不过由于找到第一个匹配的catch后就不会继续看剩余的catch了,所以这里的volatile B e
实际上永远不会用上,被上方的父类匹配屏蔽了。
在catch语句中,还可以单用一个throw重新抛出异常给上层处理:
try
{
try
{
throw "err"; // 抛出异常
}
catch (const char* e) // 内层捕获异常
{
std::cout << "Inner " << e << std::endl;
throw; // 重新抛出异常
}
catch (...) // 重新抛出也不会进入此catch,而是外层的catch。
{
std::cout << "All" << std::endl;
}
}
catch (const char* e) // 外层捕获异常
{
std::cout << "Outter " << e << std::endl;
}
/* 输出:
Inner err
Outter err
*/
参考资料
https://www.tutorialspoint.com/cplusplus/cpp_exceptions_handling.htm#:~:text=A%20C%2B%2B%20exception%20is%20a,try%2C%20catch%2C%20and%20throw.
https://en.cppreference.com/w/cpp/language/try_catch