try throw catch笔记:条款12:抛出异常与传递参数的差异;条款13:通过引用捕获异常;条款14:审慎使用异常规格

1、try throw catch写法:

try {
	if(条件为真)
		throw ...;
	... // 其余代码
}
catch (异常类型)
{
	//处理代码
}
catch (...) // 捕获所有类型异常
{
	...
}

int * point = new (std::nothrow) int;
// 禁止内存分配错误时输出异常,而是返回NULL指针。 

在触发throw时,发生栈解退:释放调用栈中内容直到遇到try块中的返回地址,将控制权交给块尾的异常处理程序catch。而不继续执行throw后其余代码

参考资料: C++ Primer Plus 15.3节

2、函数抛出异常(异常传递)与函数传参(参数传递)的区别:
1、throw抛出的永远是对象的拷贝(包括对象、引用、指针),无论该对象离开作用域时是否被析构(堆上变量、静态变量),因此和函数传参有区别,函数传引用参数时不需要拷贝
2、catch()块接收异常类型不进行隐式类型转换(除基类派生类外),被调函数则可以进行(例:try抛出的int异常,不会被处理double异常的catch块捕获)。
3、异常捕获是按照catch块的顺序进行。
在这里插入图片描述
参考资料: More Effective C++ 条款12

3、通过引用捕获异常:
当写一个 catch 子句时,异常传递到 catch 子句中有三种方式:通过指针(by pointer),通过传值(by value)或通过引用(by reference),其中引用最好,下面详述。
a) 通过指针:

try{
	...
	static exception ex;
	throw &ex; //方式一:抛出异常指针
	throw new exception; //方式二:抛出异常指针
}
catch( exception *ex;){
	...
}

通过指针的方式,对静态异常变量catch中不需要delete,但堆上异常变量需要delete,因此较复杂,同时不符合C++四个标准异常类型的语言规范。
b) 通过传值:
当异常通过传值时,需要进行拷贝两次(离开作用域一次,catch接收一次)而且它会产生 slicing problem,即派生类的异常对象被做为基类异常对象捕获时,那它的派生类行为就被切掉了(sliced off)。
c) 通过引用:

try{
	...
	exception ex;
	throw ex; //方式一:抛出异常指针
}
catch( exception &ex;){
	...
}

异常变量复制一次,避免了上述所有问题。

参考资料: More Effective C++ 条款13

4、审慎使用异常规格:
具体描述见链接,函数后加throw()修饰称为异常规格,称对这个函数的异常安全性作出限制。

void fun(); //声明函数fun,表示fun可以抛出任何形式的异常。
void fun() throw(...); //表示fun可以抛出任何形式的异常。
void fun() throw(); //表示fun不允许抛出任何异常,即fun是异常安全的。
void fun() throw(exceptionType); //表示fun只能抛出exceptionType类型的异常。

这只是程序员的一种保证,实际也可能抛出异常。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值