C++中的异常处理(一)

异常就是运行时出现的不正常,例如运行时耗尽了内存或遇到意外的非法输入。异常存在于程序的正常功能之外,并要求程序立即处理。不能不处理异常,异常是足够重要的,使程序不能继续正常执行的事件。如果找不到匹配的catch,程序就调用库函数terminate。

 

如果不处理异常将会出现上图的效果。下面是处理异常的代码:

#include<iostream>
using namespace std;
int main()
{
	try
	{
	int a=3,b=0;
	int c=a/b;
	}
	catch(...)
	{
	}

	return 0;
}


这里catch后圆括号中的...指的是捕获所有异常。

 

抛出异常的时候,将暂停当前函数的执行,,开始查找匹配的catch子句。首先检查throw本身是否在try块内部,如果是,检查与该try相关的catch子句,看是否其中之一与被抛出对象相匹配。如果找到匹配的catch,就处理异常:如果找不到,就退出当前函数(释放当前函数的内存并撤销局部对象),并继续在调用函数中查找。

 

如果对抛出异常的函数调用是在try块中,则检查与该try块相关的catch子句。如果找到匹配的catch就处理异常;如果找不到匹配的catch,调用函数也退出,并且继续在调用这个函数的函数中查找。

 

这个过程称之为栈展开,沿嵌套函数调用链继续向上,直到为异常找到一个catch子句。只要找到能够处理异常的catch子句,就进入该catch子句,并在该处理代码中继续执行。当catch子句结束的时候,在紧接在与该try块相关的最后一个catch子句之后的点继续执行。

 

在栈展开的时候,会退出某个函数,释放当前内存并撤销局部对象,这时会调用对象的析构函数,如果析构函数抛出异常,将会调用标准库terminate函数,强制整个程序非正常退出。所以析构函数应该从不抛出异常。

 

 

在查找匹配的catch期间,找到的catch不必是与异常最匹配的那个catch,相反,将选中第一个找到的可以处理该异常的catch。因此,在catch子句列表中,最特殊的catch必须最先出现,否则没有执行的机会。

 

进入catch的时候,用异常对象初始化catch的形参。因为基类的异常说明符可以捕获派生类的异常对象。如果异常对象是引用,则可以使用多态,调用基类的virtual将执行派生类的覆盖的函数。若catch的异常说明符是对象,则将派生类对象分割为它的基类对象。

 

异常的层次

异常的层次如下图:

 

exception类型所定义的唯一操作是一个名为what的虚成员,该函数返回const char* 对象,它一般返回用来在抛出位置构造异常对象的信息。因为what是虚函数,如果捕获了基类类型的引用,对what函数的调用将执行适合异常对象的动态类型的版本。

使用自定义异常

 

下面自定义异常类,继承自logic_error,MyException.h如下:

#if !defined(AFX_MYEXCEPTION_H__EB39C92B_B867_41AA_83A6_E614FD4AEC63__INCLUDED_)
#define AFX_MYEXCEPTION_H__EB39C92B_B867_41AA_83A6_E614FD4AEC63__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#include<string>
#include<stdexcept>
class MyException:public std::logic_error  
{
public:
	MyException(std::string s,std::string myinfo);
	const char* what() const;
	virtual ~MyException();
private:
	std::string myinfo;
	

};

#endif // !defined(AFX_MYEXCEPTION_H__EB39C92B_B867_41AA_83A6_E614FD4AEC63__INCLUDED_)


MyException.cpp内容如下:

#include "MyException.h"

MyException::MyException(std::string s,std::string myinfo):logic_error(s)
{
	this->myinfo=myinfo;
}

MyException::~MyException()
{

}

const char* MyException::what() const
{
	return myinfo.c_str(); 
}


main函数所在的文件内容如下:

#include<iostream>
#include"MyException.h"
using namespace std;

void getException(bool b)
{
	if(b)
	{
		throw MyException("error","the parameter is true");
	}
}

int main()
{
	try
	{
		getException(1);
	}
	catch(logic_error &e)
	{
		cout<<e.what()<<endl;
	}
	return 0;
}


运行结果如下:

 

在MyException类中,覆盖了logic_error类中的virtual函数,在catch异常说明类型使用的是基类logic_error的引用,所以输出的结果是MyException中myinfo的内容。这就是多态在异常中的使用。
  • 13
    点赞
  • 55
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值