C++ - 异常处理

18 篇文章 0 订阅

异常处理机制主要有两个主要成分:异常的鉴定与发出,以及异常的处理方式。通常,不论是member function或non-member function,都有可能产生异常以及处理异常。异常出现之后,正常程序的执行便被暂停(suspended),与此同时,异常处理机制开始搜索程序中有能力处理这一异常的地点。异常被处理完毕之后,程序的执行便会继续(resume),从异常处理点接着执行下去。

1、异常抛出(Throwing an Exception)

C++通过throw表达式产生(抛出)异常:

void divide(int x, int y)
{
	if(y == 0)
	{
		throw x; // 抛出(int)类型的异常
	}
	cout << "divide结果:" << x/y << endl;
}

如上面程序中,如果y==0,就会抛出一个int类型的异常,当执行完throw语句之后,下面的cout语句便不会再被执行。

throw表达式看起来有点像函数调用 。那么何谓抛出(thrown)一个异常?所谓异常(Exception)是某种对象。最简单的异常对象可以设计为整数或者字符串:

throw 42;
throw "there's is an exception";

但是大部分时候,被抛出的异常都属于特定的异常类(也许形成了一个继承体系) 

class it_overflow
{
public:
	it_overflow(int index, string reason):
		_index(index),
		_reason(reason){}

	void what_happened()
	{
		cout << "Internal error:current index: "
			<< _index << " reason: " << _reason << endl;
	}
private:
	int _index;
	string _reason;
};

如上,定了一个异常类,异常类的定义和普通类的定义没有什么不同。那自定义异常类是怎么抛出呢?如下所示:

void play05()
{
	int currIndex = 100;
	int maxIndex = 10;
	if(currIndex > maxIndex)
	{
		throw it_overflow(0, "the currIndex greater than maxIndex!");
	}
}

如上所示,当发生错误时,会直接抛出一个it_overflow异常类的一个匿名对象,当然我们也可以明确指出抛出的对象的名称,如下所示:

void play05()
{
	int currIndex = 100;
	int maxIndex = 10;
	if(currIndex > maxIndex)
	{
		it_overflow ex(0, "the currIndex greater than maxIndex!");
		throw ex;
	}
}

2、异常捕获(Catching an Exception)

C++中可以利用单条或一连串的catch字句看来捕获(catch)被抛出来的异常对象。catch字句由3部分组成:关键字catch,小括号内的一个类型或对象、大括号内的一组语句(用于处理异常)。

catch字句应该和try块相应而生。try块是以关键字try作为开始,然后大括号内的一连串程序语句。catch字句放在try块的末尾。这表示,如果try块内有任何异常发生,便由接下来的catch字句加以处理。如下所示:

void main()
{
	try
	{
		play05_1();
	}
	catch(it_overflow& e)    //最好写成by reference,如果是by value就需要拷贝构造函数
	{
		e.what_happened();
	}
	catch(int err)
	{
		cout << "Exception:" << errno << endl;
	}
	catch(const char* str)
	{
		cout << "Exception:" << str << endl;
	}
	catch(...)
	{
		cout << "未知异常!" << endl;
	}
	return;
}

上述程序定义了一个try块和四个catch字句,能够捕获三种类型的异常对象,其中catch(...)用于捕获未知类型的异常对象,即当抛出的异常没有catch字句进行捕获时,就会进入到catch(...)字句内。

上述的catch字句分别处理以下所抛出的三个异常对象:

throw it_overflow(0, "the currIndex greater than maxIndex!");
throw 42;
throw "there's is an exception";

需要注意的是,抛出的异常,如果在程序中没有对应的catch字句进行捕获并处理的情况下,程序会依照函数的“函数的调用链”一一向上传递,知道找到能够处理异常的catch字句,如果一直回到了main()函数还是找不到合适的catch字句,那会发生什么事呢?C++规定,每隔一场都应该被处理,因此,如果main函数内还是找不到合适的处理程序,便会调用标准库提供的terminate()--其默认行为是终端整个程序的运行

3、标准异常(The Standard Exceptions)

标准库定义了一套异常类体系(Exception class hierarchy),其根部是名为eception的抽象基类。在exception声明有一个what()虚函数,会返回一个const char*,用以表示被抛出异常的文字描述。在c++中,所有抛出的异常,都可以用eception类型进行捕获:

catch(const exception& ex)
{
    cout << ex.what() << endl; 
}

这样当处理抛出的标准异常时,只需要写一个ctach字句就可以了。

当然,我们也可以自定义一个继承自exception基类的异常类,如下所示:

Code3-2:

#include <iostream>
#include <string>
#include <sstream>    //for ostringstream 
#include <exception>    // for exception
using namespace std;

class myException: public exception
{
public:
	myException(int index, string reason):
		_index(index),
		_reason(reason){}

	//overrides exception::what()
	const char* what() const;
private:
	int _index;
	string _reason;
};

const char* myException::what() const
{
	ostringstream ex_msg;

	//将输出信息写到内存内的 ostringstream 对象之中。
	//将整数值转化为字符串表示...
	ex_msg << "Internal error:current index: "
			<< _index << " reason: " << _reason << endl;

	static string str = ex_msg.str();	//需要用static变量接收,要不然会造成程序执行结束,局部变量的内存就销毁了

	return str.c_str();
}

继承自exception基类,必须要定义what()函数!在捕获异常时,就可以直接捕获exception类型的异常对象就可以了:

//throw
myException ex(0, "the currIndex greater than maxIndex!");
throw ex;

//catch
catch(exception& ex)
{
	cout << ex.what();
}

4、自定义异常类型

自定义异常类型和3章节基本上内容差不多,只不过异常的抽象基类是自定义的,比如定义了一个自定义的异常抽象基类:myAbsException。那其他所有的异常类型对象都继承自该基类,并需要实现定义的额纯虚函数。

在捕获的时候也就只需要捕获myAbsException类型的异常对象就可以了,具体代码可参考 Code 3-2。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值