C++关键字 | throw、try、catch异常处理关键字
C++关键字 | throw、try、catch异常处理关键字
前言
throw
关键字仅可用于C++。
关于异常
异常是指在程序运行时发生的特殊情况,比如尝试除以零的操作。
在C语言中,如果程序的运行出现异常、错误,我们想提供方案处理这些异常时,我们面临许多问题,如:
- c语言没有提供统一(标准)的方式来处理错误;
- 无法保证错误会被正确的处理;
- 错误的传播无法控制,特别是在函数的嵌套调用时;
而C++提供了处理异常的关键字:
throw
、
try
、
catch
**。
抛出异常
你可以使用
throw
抛出一个异常:
throw err;
如:
throw"Division by 0!";
throw 0x12345fff;
捕获异常
使用
try
和
catch
捕获异常:
try{
...//保护代码
}catch(Ex e1){
...//异常处理
}catch(Ex e2){
...//异常处理
}catch(Ex eN){
...//异常处理
}
try
块后面通常跟着1个或多个
catch
块,用于捕获保护代码里可能抛出的异常。
当保护代码抛出异常后,程序将跳出
try
块(即使在另一个函数域中),并在
catch
块中寻找关于该异常的处理办法,
Ex e
中Ex即抛出异常的类型,e即处理异常中对异常的称呼(类似函数的参数)
实例
#include<iostream>
using namespace std;
template<class t>
t divide(t a,t b){
if(b==0) throw"Devided by zero!";
return a/b;
}
int main(){
try{
cout<<divide(10,5)<<endl
<<divide(10,0)<<endl
<<divide(18,2)<<endl;
}
catch(const char* err){
cerr<<err<<endl;//std::cerr标准错误流异常输出
}
return 0;
}
2
Devided by zero!
不难看出,当
try
块中抛出异常后,程序将第一时间退出保护代码,后面的语句不会被执行。
标准异常
C++提供了一系列标准异常,在
中,实质是一堆相互继承的父子关系类,关系如图:(
std
后要加俩
:
)
异常 描述
std::exception 该异常是所有标准 C++ 异常的父类。
std::bad_alloc 该异常可以通过 new 抛出。
std::bad_cast 该异常可以通过 dynamic_cast 抛出。
std::bad_exception 这在处理 C++ 程序中无法预期的异常时非常有用。
std::bad_typeid 该异常可以通过 typeid 抛出。
std::logic_error 理论上可以通过读取代码来检测到的异常。
std::domain_error 当使用了一个无效的数学域时,会抛出该异常。
std::invalid_argument 当使用了无效的参数时,会抛出该异常。
std::length_error 当创建了太长的 std::string 时,会抛出该异常。
std::out_of_range 该异常可以通过方法抛出,例如 std::vector 和 std::bitset<>::operator。
std::runtime_error 理论上不可以通过读取代码来检测到的异常。
std::overflow_error 当发生数学上溢时,会抛出该异常。
std::range_error 当尝试存储超出范围的值时,会抛出该异常。
std::underflow_error 当发生数学下溢时,会抛出该异常。
重载异常
你可以通过重载继承
exception
父异常类来创建自己的异常:
#include<iostream>
#include<exception>
using namespace std;
class myexception
: public exception
{
public:
const char* what() const throw() {
return "Exception : Myexception\n";
}
};
int main() {
try {
throw myexception();
}
catch (myexception mye) {
cout << "Exception caught!\n"
<< mye.what();
}
return 0;
}
Exception caught!
Exception : Myexception
一行一行看,
首先:
class myexception : public exception { public:...
表示
public
继承标准库异常类,定义类
myexception
。
const char * what() const throw()
这一句是关键,
what()
是异常类提供的公共方法,且被所有子异常类重载:
//<exception>
class exception{...
public:...
... virtual const char * what() const {...}
}
可以看到,在标准父异常类中,
what()
被定义为虚函数,因此你才能随意重载它。
what()
函数的标准是没有参数且返回值为C语言风字符串(即
const char *
)
从左往右看:
const char *
: 返回类型是字符串。what
: 函数名。()
: 参数列表,均为空。const
: 声明函数无法改变变量。throw()
: 异常规格说明,表示函数无法抛出任何异常。
看到
main()
,在
try
块里抛出了一个
myexception()
:
...
throw myexception();
...
相当于调用了myexception类的默认构造函数(没有定义构造函数,系统会自己创建一个),即创建了一个myexception对象并抛出。可以在
myexception
类中定义构造函数:
class myexception{
public:
...
myexception(){cout<<"build func used!\n";}
};
...
则输出会为:
build func used!
Exception caught!
Exception : Myexception
因此在
catch()
块中捕捉了这个myexception对象并调用
what()
方法。
异常规格说明符
- 见异常规格说明符