c++异常处理 笔记若干

Qwerty posted @ 2010年12月22日 00:58 in 程序 with tags c++ 语法 , 1017 阅读

1. 抛出异常后, 当前正在执行的代码会立刻中断执行, 转到最近的与异常类型相匹配的catch模块中执行, 当catch模块执行完毕之后, 直接从catch模块后面的代码继续执行.

2. 如果一个函数会抛出异常, 函数内部抛出了一个异常, 并且函数内部没有对这个异常进行捕捉, 那么函数会立刻终止, 甚至没有返回, 就如过goto了一样, 而异常则抛出给调用此函数的代码来处理.

3. 任何类型的异常的异常都可以抛出, 简单的从int, 复杂到类结构, 都没有问题.

4. throw语句如果抛出的是一个已经定义的类实例(结构实例), 那么会导致以这个实例为参数的拷贝构造函数的调用:

#include <stdio.h>

class ThrowTest
{
public:
	ThrowTest(){}
	ThrowTest(const ThrowTest& tt)
	{
		puts("Copy Constructor is called.");
	}
};

int main()
{
	try
	{
		ThrowTest tt;
		throw tt;
	}
	catch(ThrowTest)
	{
		puts("inside catch");
	}
	return 0;
}

输出为

Copy Constructor is called.
Copy Constructor is called.
inside catch

这里会输出两个"Copy Constructor is called."是因为catch也会调用到拷贝构造函数, 这个等下再说明.
而如果不是已经定义好的类实例(即直接调用构造函数使用临时值), 那么就只是调用该函数. (这是为了避免实例生存期结束而导致的错误?)

5. catch的模块参数只能是一个, 作用和一般的函数参数一样, 也分按值传递和按引用传递, 所以在笔记4的例子代码的输出结果是调用了两次拷贝构造函数. 如果使用

catch(Exception& e)
{
	//some code
	//...

的方法, 则不会再调用一次构造函数.

6. try模块里面定义的局部变量只能在try模块里使用, 在catch里面也不可以使用, 这个和一般的花括号一样. catch也是类似.

7. 在try模块里面可以抛出不同类型的异常, 通过不同catch模块指定不同类型的异常来捕获, 注意如果抛出的是派生类的异常, catch的异常类型是基类, 那么照样可以捕获这个异常, 但是反过来则不行. 所以在安排catch模块时要注意顺序, 如果基类catch模块先于派生类catch模块, 将导致派生类类型的异常被截断无法正确捕捉.

8. 如果不需要理会异常的具体内容, 可以不指明catch模块参数的参数名, 只写出类型即可. 如

catch(Exception)
{
	//some code
	//...

9. 函数抛出异常应指明指明异常说明(抛出列表). 抛出多种不同类型的异常用逗号隔开, 如果不指明异常说明的话等于可以抛出任何异常(等价于后面说的"...."), 用没有内容的空括号表示不抛出任何异常.

returnType function(someArgs) throw ();//no throw
returnType function(someArgs) throw (exType);//only one type
returnType function(someArgs) throw (exType1, exType2, ..., exTypeN);//multi type
returnType function(someArgs) throw (...);//all type 
returnType function(someArgs) ;//all type 

10. 用 ... (3个句号) 可以抛出任何异常和捕获任何异常.

11. 如果函数抛出了不在异常说明中列出的类型的异常, 会调用unexpected函数, unexpected函数的默认处理是调用terminate函数结束程序, 但是也可以用set_unexpected函数改变其行为. 如果抛出了异常没有被catch, 那么直接调用terminate函数.

12. 异常的抛出可以递归, 就是有f1, f2, f3 3个函数, f1调用f2, f2调用f3, f3抛出异常, f2不处理, 那么f2也结束, 异常交给f1处理.


登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter