C++标准程序库中的异常处理

C++标准提供的标准异常类

这些类以exception为基类,标准程序库抛出的类型对象,都是其派生类的对象。该类包含一个成员函数

virtual const char* what() const throw();

表明返回值为一个字符串,且不抛出任何异常。该函数可在派生类中重定义。
习惯上,我们可以使用标准库中的异常类,如果不满足程序要求,可以自定义异常类。自定义异常类建议派生自Exception类或其派生类。

各种派生标准异常类

异常类头文件及含义
bad_alloc< exception> 用new动态分配空间失败
bad_cast< new> 执行dynamic_cast失败,即基类向派生类的转换,指针为空
bad_typeid< typeinfo> 对空指针p执行typeid(*p),判断运行时多态对象的类型失败
bad_exception< typeinfo>当某一函数fun()在执行过程中抛出了异常声明不允许的异常而调用unexpected()函数时,若unexpected()函数再次抛出fun()函数异常声明所不允许的异常,且fun()异常明明列表中有bad_exception ,则会有一个bad_exception 异常在fun()函数调用点被抛出。
ios_base::failure< ios>C++的输入输出流执行过程中发生的错误。
underflow_error< stdexcept>算术运算时向下溢出
overflow_error< stdexcept>算术运算时向上溢出
rang_error< stdexcept>内部计算时发生作用域的错误
out_of_range< stdexcept>表示参数值不在允许的范围内
length_error< stdexcept>尝试创建一个长度超过最大允许值的对象
invalid_argument< stdexcept>表示向函数传的参数无效
domain_error< stdexcept>执行一段程序的先决条件不足

后七个类

  • runtime_error

underflow_error、overflow_error、rang_error这三个类其实是runtime_error的派生类。而runtime_error是exception类的派生类。runtime_error代表运行时出错,即运行时动态判断的错误。常用的就比如判断溢出。

  • logic_error

out_of_range、length_error、invalid_argument、domain_error这四个类是logic_error的派生类,logic_error同样是exception类的派生类。logic_error代表逻辑错误,及在运行前,根据程序运行逻辑能够判断出来的错误。如果小心编写程序,并使用合法输入的话,logic_error可以避免。而非法输入可能会引起函数崩溃,引入异常处理可以提高程序运行的健壮性,避免非法输入引起的程序崩溃。

传递具体的错误信息

这七个类,或者说runtime_error和logic_error都有一个接受const string&型参数的构造函数。在抛出异常构造对象时,可以将具体的错误信息传递给该函数。通过调用what()函数得到构造时提供的错误信息。

#include<iostream>
#include<stdexcept>

using namespace std;

void fun(double a) throw(out_of_range)
{
	if (a > 10)
		throw out_of_range("Parameter not in range");
}
int main()
{
	try
	{
		fun(20);
	}
	catch (exception &e)
	{
		cout << "Error:" << e.what() << endl;
	}
	return 0;
}

输出为
Error:Parameter not in range

C++标准库的稳定性

C++保证,C++标准程序库在面对异常时,保证不发生资源泄漏,也不破坏容器的不变特性。

  1. 对于以结点实现的容器,如list、set、map及multiset、multimap,如果结点构造失败,容器应当保持不变。并保证删除结点操作不会失败。
  2. 对于以数组实现的容器,如vector、deque,由于有时需要调用复制构造函数和复制赋值运算符,当这些操作失败而抛出异常时,容器的不变性不能保证,除此以外,同以结点实现的容器一样。

自定义unexpected()

通过set_unexpected()函数,参数为自定义的unexpected函数名。


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

class A
{
public:
	A();
	~A();

private:

};

A::A()
{
}

A::~A()
{
}

struct MyException
{
	const char* message;
	MyException(const char* arg) : message(arg) { }
};

void MyUnexpected()
{
	cout << "Enter MyUnexpected" << endl;
	throw MyException("Exception thrown from MyUnexpected");
}

void fun() throw(A)
{	
	cout << "enter fun()" << endl;
	throw 5;
}


int main()
{
	set_unexpected(MyUnexpected);
	try
	{
		fun();		
	}
	catch (MyException &e)
	{
		cout <<e.message << endl;
	}
	catch (int &e)
	{
		cout << e << endl;
	}

	return 0;
}

不过结果为
enter fun()
5
环境是VS2017,表明这个异常声明接口,完全没用,真的就是为了增加可读性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值