C++中的异常处理
原创
©著作权归作者所有:来自51CTO博客作者CurryCoder的原创作品,请联系作者获取转载授权,否则将追究法律责任
1.Cpp中的异常处理
2.抛出异常
- 可以使用throw语句在代码块中的任何地方抛出异常。throw语句的操作数可以是任意的表达式,表达式的结果的类型决定了抛出的异常的类型。以下是尝试除以零时抛出异常的实例:
double division(int a, int b){
if(b == 0)
throw "Division by zero condition!";
return (a / b);
}
int main(){
int a = 3;
int b = 0;
cout << "division(3, 0) = " << division(a, b) << endl;
return 0;
}
3.捕获异常
- catch块跟在try块后面,用于捕获异常。可以指定想要捕捉的异常类型,这是由catch关键字后的括号内的异常声明决定的。
try{
// 保护代码
}catch(ExceptionName e){
// 处理异常的代码
}
- 上面的代码会捕获一个类型为ExceptionName的异常。如果想让catch块能够处理try块抛出的任何类型的异常,则必须在异常声明的括号内使用省略号…,如下所示:
double division(int a, int b){
if(b == 0)
throw "Division by zero condition!";
return (a / b);
}
try{
// 保护代码
}catch(...){
// 能处理任何异常的代码
}
- 下面是一个实例,抛出一个除以零的异常,并在catch块中捕获该异常
try{
z = division(3, 0);
}catch(const char* msg){ // 常指针,等价于 char const *msg;
cerr << msg << endl;
}
- 由于抛出了一个异常类型为const char*的异常,因此,当捕获该异常时,必须在catch块中使用const char*。当上面的代码被编译和执行时,它会产生下列结果:Division by zero condition!
4.Cpp中标准的异常
- C++提供了一系列标准的异常,定义在中,可以在程序中使用这些标准的异常。它们是以父子类层次结构组织起来的,如下所示:
- 下表是对上面层次结构中出现的每个异常的说明:
5.定义新的异常
- 可以通过继承和重载exception类来定义新的异常。下面的实例演示了如何使用std::exception类来实现自己的异常:
#include "iostream"
#include "exception"
using namespace std;
// 自定义新的异常
struct MyException: public exception{
const char * what() const throw(){ // what()是异常类提供的一个公共方法,它已被所有子异常类重载,这将会返回异常产生的原因。
return "C++ Exception!";
}
};
try{
throw MyException();
}catch(MyException &e){
cout << "MyException caught: ";
cout << e.what() << endl;
}
- what()是异常类提供的一个公共方法,它已被所有子异常类重载,这将会返回异常产生的原因。
-
const throw()不是函数,这个东西叫异常规格说明,表示what函数可以抛出异常的类型,类型说明放到()里,这里面没有类型,就是声明这个函数不抛出异常;通常函数不写后面的就表示函数可以抛出任何类型的异常。
- 异常规格说明:
- 异常规格说明的目的是为了让函数使用者知道该函数可能抛出的异常有哪些。可以在函数的声明中列出这个函数可能抛掷的所有异常类型。例如:
void fun() throw(A, B, C, D);
- 若无异常接口声明,则此函数可以抛掷任何类型的异常
- 不抛掷任何类型异常的函数声明如下:
// 基类
class MyException{
public:
MyException(const char * msg): message(msg){
cout << "构造函数MyException类的对象.....\n";
}
MyException(const MyException &other): message(other.message){
cout << "拷贝构造函数MyException类的对象......\n";
}
// 析构函数
virtual ~MyException(){
cout << "~MyException.....\n";
}
const char *what() const{
return message.c_str();
}
private:
string message;
};
// 派生类
class MyExceptionD: public MyException{
public:
MyExceptionD(const char *message): MyException(message){
cout << "构造函数MyExceptionD类的对象......\n";
}
MyExceptionD(const MyExceptionD & other): MyException(other){
cout << "拷贝构造函数MyExceptionD类的对象......\n";
}
// 析构函数
~MyExceptionD(){
cout << "~MyExceptionD......\n";
}
};
void fun(int n) throw(int, MyException, MyExceptionD){
if(n == 1)
throw 1;
else if(n == 2)
throw MyException("Test Exception......");
else if(n == 3)
throw MyExceptionD("Test MyExceptionD......");
}
void fun2() throw(){
}
try{
fun(2);
}catch(int n){
cout << "catch int......\n";
cout << "n = " << n << endl;
}catch(MyExceptionD &e){
cout << "catch MyExceptionD......\n";
cout << e.what() << endl;
}catch(MyException &e){
cout << "catch MyException......\n";
cout << e.what() << endl;
}
- 在C++11中,声明一个函数不可以抛出任何异常使用关键字noexcept,见下面的实例:
void mightThrow(); // could throw any exceptions.
void doesNotThrow() noexcept; // does not throw any exceptions.
- 下面两个函数声明的异常规格在语义上是相同的,都表示函数不抛出任何异常。
void old_stytle() throw();
void new_style() noexcept;