C++关键字 | throw、try、catch异常处理关键字

前言

throw关键字仅可用于C++


关于异常

异常是指在程序运行时发生的特殊情况,比如尝试除以零的操作。

在C语言中,如果程序的运行出现异常、错误,我们想提供方案处理这些异常时,我们面临许多问题,如:

  1. c语言没有提供统一(标准)的方式来处理错误;
  2. 无法保证错误会被正确的处理;
  3. 错误的传播无法控制,特别是在函数的嵌套调用时;

而C++提供了处理异常的关键字:throwtrycatch

抛出异常

你可以使用throw抛出一个异常:

throw err;

如:

throw"Division by 0!";
throw 0x12345fff;

捕获异常

使用trycatch捕获异常:

try{
	...//保护代码
}catch(Ex e1){
	...//异常处理
}catch(Ex e2){
	...//异常处理
}catch(Ex eN){
	...//异常处理
}

try块后面通常跟着1个或多个catch块,用于捕获保护代码里可能抛出的异常。
当保护代码抛出异常后,程序将跳出try块(即使在另一个函数域中),并在catch块中寻找关于该异常的处理办法,Ex e中Ex即抛出异常的类型,e即处理异常中对异常的称呼(类似函数的参数)
实例

#include<iostream>
using namespace std;
template<class t>
t divide(t a,t b){
	if(b==0) throw"Devided by zero!";
	return a/b;
}
int main(){
	try{
		cout<<divide(10,5)<<endl
			<<divide(10,0)<<endl
			<<divide(18,2)<<endl;
		}
	catch(const char* err){
		cerr<<err<<endl;//std::cerr标准错误流异常输出
	}
	return 0;
}
2
Devided by zero!

不难看出,当try块中抛出异常后,程序将第一时间退出保护代码,后面的语句不会被执行。

标准异常

C++提供了一系列标准异常,在<exception>中,实质是一堆相互继承的父子关系类,关系如图:(std后要加俩:
在这里插入图片描述

异常描述
std::exception该异常是所有标准 C++ 异常的父类。
std::bad_alloc该异常可以通过 new 抛出。
std::bad_cast该异常可以通过 dynamic_cast 抛出。
std::bad_exception这在处理 C++ 程序中无法预期的异常时非常有用。
std::bad_typeid该异常可以通过 typeid 抛出。
std::logic_error理论上可以通过读取代码来检测到的异常。
std::domain_error当使用了一个无效的数学域时,会抛出该异常。
std::invalid_argument当使用了无效的参数时,会抛出该异常。
std::length_error当创建了太长的 std::string 时,会抛出该异常。
std::out_of_range该异常可以通过方法抛出,例如 std::vector 和 std::bitset<>::operator
std::runtime_error理论上不可以通过读取代码来检测到的异常。
std::overflow_error当发生数学上溢时,会抛出该异常。
std::range_error当尝试存储超出范围的值时,会抛出该异常。
std::underflow_error当发生数学下溢时,会抛出该异常。

重载异常

你可以通过重载继承exception父异常类来创建自己的异常:

#include<iostream>
#include<exception>
using namespace std;

class myexception 
	: public exception
{
public:
	const char* what() const throw() {
		return "Exception : Myexception\n";
	}
};

int main() {
	try {
		throw myexception();
	}
	catch (myexception mye) {
		cout << "Exception caught!\n"
			<< mye.what();
	}
	return 0;
}
Exception caught!
Exception : Myexception

一行一行看,
首先:

class myexception : public exception { public:...

表示public继承标准库异常类,定义类myexception


const char * what() const throw()

这一句是关键,what()是异常类提供的公共方法,且被所有子异常类重载:

//<exception>
class exception{...
public:...
	... virtual const char * what() const {...} 
}

可以看到,在标准父异常类中,what()被定义为虚函数,因此你才能随意重载它。what()函数的标准是没有参数且返回值为C语言风字符串(即const char *
从左往右看:

  • const char * : 返回类型是字符串。
  • what : 函数名。
  • () : 参数列表,均为空。
  • const : 声明函数无法改变变量。
  • throw() : 异常规格说明,表示函数无法抛出任何异常。




看到main(),在try块里抛出了一个myexception()

...
throw myexception();
...

相当于调用了myexception类的默认构造函数(没有定义构造函数,系统会自己创建一个),即创建了一个myexception对象并抛出。可以在myexception类中定义构造函数:

class myexception{
public:
	...
	myexception(){cout<<"build func used!\n";}
};
...

则输出会为:

build func used!
Exception caught!
Exception : Myexception

因此在catch()块中捕捉了这个myexception对象并调用what()方法。


异常规格说明符



@HaohaoCppDebuger|寻兰 
2021/12/20 

-----THE END-----
THANK YOU !

  • 3
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值