异常类型和异常变量的生命周期

Posted gd-luojialin

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了异常类型和异常变量的生命周期相关的知识,希望对你有一定的参考价值。

1)throw的异常是有类型的,可以使,数字、字符串、类对象。

2)throw的异常是有类型的,catch严格按照类型进行匹配。

3)注意 异常对象的内存模型  。

 

一、 传统处理错误

//文件的二进制copy
int filecopy01(char *filename2, char *filename1 )
{
	FILE *fp1= NULL,  *fp2 = NULL;

	fp1 = fopen(filename1, "rb");
	if (fp1 == NULL)
	{
		return 1;
	}

	fp2 = fopen(filename2, "wb");
	if (fp1 == NULL)
	{
		return 2;
	}

	char buf[256];
	int  readlen, writelen;
	while ( (readlen = fread(buf, 1, 256, fp1)) > 0 ) //如果读到数据,则大于0 
	{
		writelen = fwrite(buf, 1, readlen, fp2);
		if (readlen != readlen)
		{
			return 3;
		}
	}

	fclose(fp1);
	fclose(fp2);
	return 0;
}
测试程序
void main()
{
	int ret;
	ret = filecopy01("c:/1.txt","c:/2.txt");
	if (ret !=0 )
	{
		switch(ret)
		{
		case 1:
			printf("打开源文件时出错!
");
			break;
		case 2:
			printf("打开目标文件时出错!
");
			break;
		case 3:
			printf("拷贝文件时出错!
");
			break;
		default:
			printf("发生未知错误!
");
			break;
		}
	}
}

 

 

二、throw int类型异常

/文件的二进制copy
void filecopy02(char *filename2, char *filename1 )
{
	FILE *fp1= NULL,  *fp2 = NULL;

	fp1 = fopen(filename1, "rb");
	if (fp1 == NULL)
	{
		//return 1;
		throw 1;
	}

	fp2 = fopen(filename2, "wb");
	if (fp1 == NULL)
	{
		//return 2;
		throw 2;
	}

	char buf[256];
	int  readlen, writelen;
	while ( (readlen = fread(buf, 1, 256, fp1)) > 0 ) //如果读到数据,则大于0 
	{
		writelen = fwrite(buf, 1, readlen, fp2);
		if (readlen != readlen)
		{
			//return 3;
			throw 3;
		}
	}

	fclose(fp1);
	fclose(fp2);
	return ;
}

  

三、throw字符类型异常

//文件的二进制copy
void filecopy03(char *filename2, char *filename1 )
{
	FILE *fp1= NULL,  *fp2 = NULL;

	fp1 = fopen(filename1, "rb");
	if (fp1 == NULL)
	{
		throw "打开源文件时出错";
	}

	fp2 = fopen(filename2, "wb");
	if (fp1 == NULL)
	{
		throw "打开目标文件时出错";
	}

	char buf[256];
	int  readlen, writelen;
	while ( (readlen = fread(buf, 1, 256, fp1)) > 0 ) //如果读到数据,则大于0 
	{
		writelen = fwrite(buf, 1, readlen, fp2);
		if (readlen != readlen)
		{
			throw "拷贝文件过程中失败";
		}
	}

	fclose(fp1);
	fclose(fp2);
	return ;
}

  

四、throw类对象类型异常

//throw int类型变量
//throw 字符串类型
//throw 类类型
class BadSrcFile 
{
public:
	BadSrcFile()
	{
		cout << "BadSrcFile 构造 do "<<endl;
	}
	~BadSrcFile()
	{
		cout << "BadSrcFile 析构 do "<<endl;
	}
	BadSrcFile(BadSrcFile & obj)
	{
		cout << "拷贝构造  do "<<endl;
	}
	void toString()
	{
		cout << "aaaa" << endl;
	}

};
class BadDestFile {};
class BadCpyFile {};;

void filecopy04(char *filename2, char *filename1 )
{
	FILE *fp1= NULL,  *fp2 = NULL;

	fp1 = fopen(filename1, "rb");
	if (fp1 == NULL)
	{
		//throw new BadSrcFile();
		throw  BadSrcFile();
	}

	fp2 = fopen(filename2, "wb");
	if (fp1 == NULL)
	{
		throw BadDestFile();
	}

	char buf[256];
	int  readlen, writelen;
	while ( (readlen = fread(buf, 1, 256, fp1)) > 0 ) //如果读到数据,则大于0 
	{
		writelen = fwrite(buf, 1, readlen, fp2);
		if (readlen != readlen)
		{
			throw BadCpyFile();
		}
	}

	fclose(fp1);
	fclose(fp2);
	return ;
}

main测试案例 //结论://C++编译器通过throw 来产生对象,C++编译器再执行对应的catch分支,相当于一个函数调用,把实参传递给形参。 void main() { try { //filecopy02("c:/1.txt","c:/2.txt"); // filecopy03("c:/1.txt","c:/2.txt"); filecopy04("c:/1.txt","c:/2.txt"); } catch (int e) { printf("发生异常:%d ", e); } catch (const char * e) { printf("发生异常:%s ", e); } catch ( BadSrcFile *e) { e->toString(); printf("发生异常:打开源文件时出错! "); } catch ( BadSrcFile &e) { e.toString(); printf("发生异常:打开源文件时出错! "); } catch ( BadDestFile e) { printf("发生异常:打开目标文件时出错! "); } catch ( BadCpyFile e) { printf("发生异常:copy时出错! "); } catch(...) //抓漏网之鱼 { printf("发生了未知异常! 抓漏网之鱼 "); } //class BadSrcFile {}; //class BadDestFile {}; //class BadCpyFile {};; }

  

异常的层次结构(继承在异常中的应用)

1.异常是类 – 创建自己的异常类

2.异常派生

3.异常中的数据:数据成员

4.按引用传递异常

  -->在异常中使用虚函数

 

五、标准程序库异常

技术分享图片

技术分享图片

技术分享图片

技术分享图片

 

 

案例1:

#include "iostream"
using namespace std;
#include <stdexcept>  
 
class Teacher
{
public:
	Teacher(int age)  //构造函数, 通过异常机制 处理错误
	{
		if (age > 100)
		{
			throw out_of_range("年龄太大");
		}
		this->age = age;
	}
protected:
private:
	int age;
};

void mainxx()
{
	try
	{
		Teacher t1(102);
	}
	catch (out_of_range e)
	{
		
		cout << e.what() << endl;
	}

	exception e;
	system("pause");
}

  

 

案例2

class Dog
{
public:
	Dog()
	{
		parr = new int[1024*1024*100]; //4MB
	}
private:
	int *parr;
};

int main31()
{
	Dog *pDog;
	try{
		for(int i=1; i<1024; i++) //40GB!
		{
			pDog = new Dog();
			cout << i << ": new Dog 成功." << endl;
		}
	}
	catch(bad_alloc err)
	{
		cout << "new Dog 失败: " << err.what() << endl;
	}

	return 0;

}

  

案例3

技术分享图片

技术分享图片

技术分享图片技术分享图片

 



以上是关于异常类型和异常变量的生命周期的主要内容,如果未能解决你的问题,请参考以下文章

“异常对象的生命周期”及“匿名对象抛出和引用接收的最优操作”

ECR 生命周期策略异常

JVM 类加载

异常情况下的Activity生命周期分析

Activity在异常情况下的生命周期——Android开发艺术探索笔记

Android之Activity生命周期的浅析