C++异常类型以及多级catch匹配?!
Posted C语言学习联盟
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C++异常类型以及多级catch匹配?!相关的知识,希望对你有一定的参考价值。
// 可能抛出异常的语句
}catch(exceptionType variable){
// 处理异常的语句
}
exceptionType variable
,这节就来详细分析一下。exceptionType
是异常类型,它指明了当前的 catch 可以处理什么类型的异常;
variable
是一个变量,用来接收异常信息。当程序抛出异常时,会创建一份数据,这份数据包含了错误信息,程序员可以根据这些信息来判断到底出了什么问题,接下来怎么处理。异常既然是一份数据,那么就应该有数据类型。C++ 规定,异常类型可以是 int、char、float、bool 等基本类型,也可以是指针、数组、字符串、结构体、类等聚合类型。C++ 语言本身以及标准库中的函数抛出的异常,都是 exception 类或其子类的异常。也就是说,抛出异常时,会创建一个 exception 类或其子类的对象。
exceptionType variable
和函数的形参非常类似,当异常发生后,会将异常数据传递给 variable 这个变量,这和函数传参的过程类似。当然,只有跟 exceptionType 类型匹配的异常数据才会被传递给 variable,否则 catch 不会接收这份异常数据,也不会执行 catch 块中的语句。换句话说,catch 不会处理当前的异常。我们可以将 catch 看做一个没有返回值的函数,当异常发生后 catch 会被调用,并且会接收实参(异常数据)。
但是 catch 和真正的函数调用又有区别:
-
真正的函数调用,形参和实参的类型必须要匹配,或者可以自动转换,否则在编译阶段就报错了。 -
而对于 catch,异常是在运行阶段产生的,它可以是任何类型,没法提前预测,所以不能在编译阶段判断类型是否正确,只能等到程序运行后,真的抛出异常了,再将异常类型和 catch 能处理的类型进行匹配,匹配成功的话就“调用”当前的 catch,否则就忽略当前的 catch。
总起来说,catch 和真正的函数调用相比,多了一个「在运行阶段将实参和形参匹配」的过程。
另外需要注意的是,如果不希望 catch 处理异常数据,也可以将 variable 省略掉,也即写作:
// 可能抛出异常的语句
}catch(exceptionType){
// 处理异常的语句
}
多级 catch
try{ //可能抛出异常的语句 }catch (exception_type_1 e){ //处理异常的语句 }catch (exception_type_2 e){ //处理异常的语句 } //其他的catch catch (exception_type_n e){ //处理异常的语句 }
下面的例子演示了多级 catch 的使用:
#include <iostream> #include <string> using namespace std; class Base{ }; class Derived: public Base{ }; int main(){ try{ throw Derived(); //抛出自己的异常类型,实际上是创建一个Derived类型的匿名对象 cout<<"This statement will not be executed."<<endl; }catch(int){ cout<<"Exception type: int"<<endl; }catch(char *){ cout<<"Exception type: cahr *"<<endl; }catch(Base){ //匹配成功(向上转型) cout<<"Exception type: Base"<<endl; }catch(Derived){ cout<<"Exception type: Derived"<<endl; } return 0; }
Exception type: Base
我们期望的是,异常被
catch(Derived)
捕获,但是从输出结果可以看出,异常提前被
catch(Base)
捕获了,这说明 catch 在匹配异常类型时发生了向上转型(Upcasting)。
catch 在匹配过程中的类型转换
-
算数转换:例如 int 转换为 float,char 转换为 int,double 转换为 int 等。 -
向上转型:也就是派生类向基类的转换。 -
const 转换:也即将非 const 类型转换为 const 类型,例如将 char * 转换为 const char *。 -
数组或函数指针转换:如果函数形参不是引用类型,那么数组名会转换为数组指针,函数名也会转换为函数指针。 -
用户自定的类型转换。
catch 在匹配异常类型的过程中,也会进行类型转换,但是这种转换受到了更多的限制,仅能进行「向上转型」、「const 转换」和「数组或函数指针转换」,其他的都不能应用于 catch。
向上转型在上面的例子中已经发生了,下面的例子演示了 const 转换以及数组和指针的转换:
#include <iostream> using namespace std; int main(){ int nums[] = {1, 2, 3}; try{ throw nums; cout<<"This statement will not be executed."<<endl; }catch(const int *){ cout<<"Exception type: const int *"<<endl; } return 0; }
Exception type: const int *
nums 本来的类型是
int [3]
,但是 catch 中没有严格匹配的类型,所以先转换为
int *
,再转换为
const int *
。
以上是关于C++异常类型以及多级catch匹配?!的主要内容,如果未能解决你的问题,请参考以下文章