前言

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后要加俩:

Java中的什么关键字用于捕获异常 用来捕获异常的关键字_c++

异常

描述

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()方法。

异常规格说明符

  • 见异常规格说明符