码迷,mamicode.com
首页 > 编程语言 > 详细

《C++Primer》读书笔记--异常处理

时间:2015-06-14 09:30:05      阅读:151      评论:0      收藏:0      [点我收藏+]

标签:c++11   c++   异常处理   异常   工具   

定义:

异常,让一个函数可以在发现自己无法处理的错误时抛出一个异常,希望它的调用者可以直接或者间接处理这个问题。


之前写的一些小程序,几乎没有用到过异常处理。因为规模比较小,一般的问题在函数内就加上一些判断条件解决了,一般的做法就是返回一个表示错误的值(比如返回NULL指针),在调用的时候判断一下返回的值,虽然简单,但是功能并不强大,只适合小型项目。而大型的项目,如果这么搞就乱套了,所以就要用到异常处理这一套系统。


一个最简单的异常处理:

// ConsoleApplication3.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <iostream>
#include <vector>
#include <string>
using namespace std;


//异常类
class NumberException{};

void NumOption(const int& a, const int& b)
{
	try
	{
		if (b == 0)
			throw NumberException();
		cout<<a / b<<endl;
	}
	catch(const NumberException& e)
	{
		cout<<"Exception!"<<endl;
	}
}


int _tmain(int argc, _TCHAR* argv[])
{
	
	int a,b;
	cin>>a;
	cin>>b;
	NumOption(a, b);
	system("pause");
	return 0;
}

结果:
//输入
1
0
//输出
Exception!


关于异常处理有下面几点要注意:

1.在抛出一个异常之后,代码会转到异常处理的地方执行,throw后面的代码就不会再执行。如果没有找到相关catch,会跳出一级继续寻找。这个过程成为栈展开。所以要注意这样一种情况,在栈展开的过程中,程序块中的各种临时对象都会被销毁。
一个例子:
// ConsoleApplication3.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <iostream>
#include <vector>
#include <string>
using namespace std;


//异常类
class NumberException{};

//测试的类
class Test
{
public:
	~Test()
	{
		cout<<"Test is destructed!"<<endl;
	}
};

void NumOption(const int& a, const int& b)
{
	
	try
	{
		Test test;
		if (b == 0)
			throw NumberException();
		cout<<a / b<<endl;
	}
	catch(const NumberException& e)
	{
		cout<<"Exception!"<<endl;
	}
}


int _tmain(int argc, _TCHAR* argv[])
{
	
	int a,b;
	cin>>a;
	cin>>b;
	NumOption(a, b);

	system("pause");
	return 0;
}

正常情况:
//输入
1
1
//输出
1
Test is destructed!

异常情况:
//输入
1
0
//输出
Test is destructed!
Exception!


从上面的结果我们可以看出,正常情况下,程序执行完,先输出1,再销毁Test对象。但是抛出异常时,显然还没有出块的作用域,但是异常发生了,throw后面的内容不执行,也相当于声明周期结束,所有临时对象都会被销毁。


2.通常情况下,接受异常的catch块最好设定为引用类型。如果设为值传递,那么会发生基类参数接受子类异常时削去子类特有部分的情况。
并且我们可以设定是否为const引用,决定是否可以在catch块中对异常进行修改。

3.catch的匹配原则:越专门的匹配越靠前,换句话说,如果同时有子类和基类异常处理的catch,而抛出的是子类异常,我们为了能够处理子类,需要把子类异常处理放在前面。
例子:
// ConsoleApplication3.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <iostream>
#include <vector>
#include <string>
using namespace std;


//异常类
class NumberException{};
//派生的异常类
class ZeroException : public NumberException {};



void NumOption(const int& a, const int& b)
{
	
	try
	{
		if (b == 0)
			throw ZeroException();
		cout<<a / b<<endl;
	}

	catch(const ZeroException& e)
	{
		cout<<"ZeroException!"<<endl;
	}

	catch(const NumberException& e)
	{
		cout<<"NumberException!"<<endl;
	}
}


int _tmain(int argc, _TCHAR* argv[])
{
	
	int a,b;
	cin>>a;
	cin>>b;
	NumOption(a, b);

	system("pause");
	return 0;
}
结果:
1
0
//输出
ZeroException!

但是如果我们把catch(cost NumberException& e)和catch(const ZeroException& e)这两个换一下位置:结果就变成了
NumberException!

可见,要想处理更特例的异常,就要越放在前面。否则父类匹配了之后,不会再匹配子类。


4.重新抛出,当我们处理了一个异常但是没处理全时,可以将异常继续抛出。使用throw;关键字可以继续抛出。但是如果没有相应的catch继续接受异常的话,程序会terminate!
一个嵌套处理异常的例子:
// ConsoleApplication3.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <iostream>
#include <vector>
#include <string>
using namespace std;


//异常类
class NumberException{};
//派生的异常类
class ZeroException : public NumberException {};



void NumOption(const int& a, const int& b)
{
	try
	{
		if (b == 0)
			throw ZeroException();
		cout<<a / b<<endl;
	}

	catch(const ZeroException& e)
	{
		cout<<"ZeroException!"<<endl;
		throw;
	}



	catch (...)
	{
		cout<<"I can solve all Exception!"<<endl;
	}
}


int _tmain(int argc, _TCHAR* argv[])
{
	
	int a,b;
	cin>>a;
	cin>>b;
	//嵌套异常处理
	try
	{
		NumOption(a, b);
	}
	catch(const NumberException& e)
	{
		cout<<"NumberException!"<<endl;
	}


	system("pause");
	return 0;
}
结果:
1
0
//输出
ZeroException!
NumberException!
抛出异常时,先通过ZeroException异常处理,处理后继续抛出,外面的NumberException接收。



5.使用catch(...)可以捕获所有的异常:
catch (...)
	{
		cout<<"I can solve all Exceptions!"<<endl;
	}

6.为了加强程序的可读性,使函数的用户能够方便地知道所使用的函数会抛出哪些异常,可以在函数的声明中列出这个函数可能抛出的所有异常类型,例如:
void fun() throw( A,B,C,D);
这表明函数fun()可能并且只可能抛出类型(A,B,C,D)及其子类型的异常。
如果在函数的声明中没有包括异常的接口声明,则此函数可以抛出任何类型的异常,例如:
void fun();
一个不会抛出任何类型异常的函数可以进行如下形式的声明:
void fun() thow();





《C++Primer》读书笔记--异常处理

标签:c++11   c++   异常处理   异常   工具   

原文地址:http://blog.csdn.net/puppet_master/article/details/46486925

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!