为了能够编写适当的catch子句,了解一个函数是否抛出异常或会抛出哪些异常对函数的用户来说是很有帮助的。
而我们可以通过 异常说明 进行对一个函数的异常进行说明, 如果函数抛出异常,被抛出的异常将是包含在该说明中的一种或是从列出的异常中派生的类型。
异常说明有如下的几种形式:
1. 指定异常
T funNname( parameterlist ) throw( T1, T2,····,Tn);
其中 T 是类型, parameterlist 是参数列表, 而类型 T1, T2,····,Tn 是函数会抛出的异常。
2. 不抛出异常
T funNname( parameterlist ) throw( );
抛出异常类型列表为空,表示的是该函数不抛出任何类型异常。
3. 抛出任意类型的异常
T funNname( parameterlist );
这表示该函数可以抛出任意类型的异常。
下面通过一段简单的代码来说明异常说明的特别之处
- #include
- class demo
- {
- };
- using namespace std;
-
- double divd(int a, int b) throw(int) //异常说明,表示函数divd会抛出类型为int的异常
- {
- if(b == 0) throw demo(); //抛出类型为demo的异常
-
- return a/b;
- }
- int main()
- {
- try
- {
- divd(1,0);
- }
- catch(demo) //捕获异常类型demo
- {
- cout << " divided by zero " << endl;
- }
- catch(int) //捕获异常类型int
- {
- cout<<"zero"<
- }
-
- return 0;
- }
这段代码的运行结果是输出: divided by zero奇怪了,在 divd 函数的声明中,只说明了抛出类型为 int 的异常,为什么其函数内抛出的异常类型却为demo呢?
我们可以暂时理解为:在某函数的异常说明中的列出的类型与该函数内抛出的异常类型不完全匹配时, 但在异常处理代码中的catch有对其类型的捕获, 所以程序运行正常。
好,下面我们根据异常说明进行一些修改
- double divd(int a, int b) throw( ) //将throw(int) 改为 throw( )
修改之后,编译运行,看到的输出结果还是: divided by zero根据上面对异常说明的三种形式介绍,我们知道在函数声明后面添加 throw()的意思是说明了此函数不会抛出任何的异常。那为什么这里抛出了而且又被捕获呢?
其实,在编译的时候,编译器不能也不会试图验证异常说明。因不能在编译时检查异常说明,异常说明的应用通常是有限的!
修改后的 divd 函数内继续编写有抛出异常的代码, 编译后再次运行程序,其输出结果也表示异常机制执行正常。
其原因就如上述所说的理解那样:编译器不会对异常说明进行检测,异常说明更多的是写给函数的用户看。
而在一开始函数异常说明的类型与实际抛出的异常类型不匹配的情况中,同样由于 “编译器不会对异常说明进行检测” 的原因,所以编译通过,异常机制运行正常。
总结:异常说明还是有用的!但更多是写给函数用户看的。让函数用户清楚知道抛出的异常类型,从而更好和正确地在运用此函数时,编写对其的异常检测。
由于初学者在学语法的时候,更多的只是看书,不进行实践验证。就算实践验证了,也可能只是照书上代码敲,看看运行结果是否一样。这里给出一个建议:初学者在学习语法的时候,应该多上机实践验证书上语法的准确性,就算运行结果与书上一致,也应该多动脑筋,对其进行变形或改动。这样往往能学到的东西和印象都会更深的!
阅读(1008) | 评论(0) | 转发(0) |