异常处理机制

异常处理机制

异常是一种程序控制机制,与函数机制互补

​ 函数是一种以栈结构展开的上下函数衔接的程序控制系统,异常是另一种控制结构,它可以在出现“意外”时中断当前函数,并以某种机制(类型匹配)回馈给隔代的调用者相关的信息

传统错误处理机制

  1. 通过函数返回值来处理错误

  2. #include <stdio.h>
    #include <stdlib.h>
    #include <string>
    
    #define BUFSIZE 1024
    
    //实现文件的二进制拷贝
    int copyfile2(const char* dest, const char* src) {
    	FILE* fp1 = NULL, * fp2 = NULL;
    	
    	//rb 只读方式打开一个二进制文件,只允许读取数据
    	fopen_s(&fp1, src, "rb");
    
    	if (fp1 == NULL) {
    		//return -1;
    		throw new std::string("文件不存在");
    	}
    
    	//wb 以只写的方式打开或新建一个二进制文件,只允许写数据
    	fopen_s(&fp2, dest, "wb");
    	if (fp2 == NULL) {
    		//return -2;
    		throw - 2;
    	}
    
    	char buffer[BUFSIZE];
    	int readlen, writelen;
    
    	while ((readlen = fread(buffer, 1, BUFSIZE, fp1))>0) {
    		writelen = fwrite(buffer, 1, readlen, fp2);
    		if (readlen != writelen) {
    			//return -3;
    			throw - 3;
    		}
    	}
    
    	fclose(fp1);
    	fclose(fp2);
    
    	return 0;
    }
    int copyfile1(const char* dest, const char* src) {
    	return copyfile2(dest, src);
    }
    int main(void) {
    	int ret = 0;
    	//ret = copyfile1("E:/奇牛培训/学习笔记/异常处理机制/dest.txt", "E:/奇牛培训/学习笔记/异常处理机制/src.txt");
    	try {
    		ret = copyfile1("E:/奇牛培训/学习笔记/异常处理机制/dest.txt", "E:/奇牛培训/学习笔记/异常处理机制/src.txt");
    	}
    	catch(int error){
    		//出现异常就会直接抛出来,不需要一层一层地递归返回值
    		printf("出现异常啦;%d\n",error);
    	}catch (std::string *error) {
    		printf("出现字符串异常:%s\n", error->c_str());
    	}
    	/*
    	if (ret != 0) {
    		switch (ret)
    		{
    		case -1:
    			printf("打开源文件失败\n");
    			break;
    		case -2:
    			printf("打开目标文件失败\n");
    			break; 
    		case -3:
    			printf("拷贝文件时出错\n");
    			break;
    		default:
    			printf("出现未知情况\n");
    			break;
    		}
    	}
    	*/
    }
    

异常处理基本语法

"异常发生第一现场,抛出异常"
void function(){
	//...
    throw 表达式
    //...
}
"在需要关注异常地地方,捕捉异常"
try{
    //程序
    function();
    //程序
}catch(异常类型声明){
    //...异常处理代码...
}catch(异常类型声明){
    //...异常处理代码...
}catch(...){
    //类型太多,用...来表示
}
  • 通过throw操作创建一个异常对象并抛出

  • 在需要捕捉异常地地方,将可能抛出异常地程序段嵌在try块之中

  • 按正常地程序顺序执行到try语句,然后执行try块{}内地保护段

  • 如果在保护段期间没有引起异常,那么跟在try块后的catch子句就不执行

  • catch子句按其在try块后出现的顺序被检查,匹配的catch子句将捕获并按catch子句中的代码处理异常(或继续抛掷异常)

  • 如果没有找到匹配,则缺省功能是调用abort终止程序。

  • 处理不了地异常,我们可以在catch的最后一个分支,使用throw语法继续向调用者throw

异常接口声明

1、对于异常接口的声明,在函数声明中"列出可能抛出的所有异常类型"
2、如果"没有"包含异常接口声明,此函数可以"抛出任何类型"的异常
3、如果函数声明中有列出可能抛出的"所有异常类型",那么抛出其他类型的异常可能"导致程序终止"
4、如果一个函数"不想抛出"任何异常,可以使用 throw() 声明
实现文件的二进制拷贝
int copyfile2(const char* dest, const char* src) throw(float,string*,int);

异常类型和生命周期

  • throw基本类型:

    • 和函数返回传值是一样的

  • throw字符串类型:

    • 实际抛出的指针,而且,修饰指针的const也要严格进行类型匹配

  • throw 类对象类型异常

    • 最佳的方式是使用引用类型捕捉,抛出匿名对象

      当然,如果是动态分配的对象,直接抛出其指针

      引用和普通的形参传值不能共存

    • try{//保护段
          //printf("开始执行 copyfile1...\n");
          ret = copyfile1("c:/test/dest.txt", "c:/test/src.txt");
          //printf("执行 copyfile1 完毕\n");
      
      }catch(ErrorException error){//不能共存   普通
          printf("出现异常啦!捕捉到 ErrorException 类型 id: %d\n", error.id);
      }catch(ErrorException &error){//不能共存  引用
          //error.id = 2;
          printf("出现异常啦!捕捉到 ErrorException &类型 id: %d\n", error.id);
      }catch(ErrorException *error){
          printf("出现异常啦!捕捉到 ErrorException *类型 id: %d\n", error->id);
          delete error;
      }catch(...){
          printf("没捉到具体的异常类型\n");
      }
      

继承与异常

异常也是类,我们可以创建自己的异常类,在异常中可以使用(虚函数,派生,引用传递和数据成员等

#include <iostream>

using namespace std;

/*
案例:设计一个数组类容器 Vector,重载[]操作,数组初始化时,对数组的个数进行有效检查
1)index<0 抛出异常errNegativeException
2)index = 0 抛出异常 errZeroException
3)index>1000抛出异常errTooBigException
4)index<10 抛出异常errTooSmallException
5)errSizeException类是以上类的父类,实现有参数构造、并定义virtual void printError()输出错误。
*/

class Vector {
public:
	Vector(int size = 128);//构造函数
	Vector(const Vector& object);//拷贝构造函数

	int getLength();//获取内部储存的元素个数

	int& operator[](int index);

	~Vector();
private:
	int* m_base;
	int m_len;
};
class errSizeException {
public:
	errSizeException(int size) {
		m_size = size;
	}
	virtual void printError() {
		cout << "size: " << m_size << endl;
	}
protected:
	int m_size;
};
class errNegativeException :public errSizeException{
public:
	errNegativeException(int size) :errSizeException(size) {

	}
	virtual void printError() {
		cout << "errNegativeException size: " << m_size << endl;
	}
};
class errZeroException :public errSizeException {
public:
	errZeroException(int size) :errSizeException(size) {

	}
	virtual void printError() {
		cout << "errZeroException size: " << m_size << endl;
	}
};
class errTooBigException :public errSizeException {
public:
	errTooBigException(int size) :errSizeException(size) {

	}
	virtual void printError() {
		cout << "errTooBigException size: " << m_size << endl;
	}
};
class errTooSmallException :public errSizeException {
public:
	errTooSmallException(int size) :errSizeException(size) {

	}
	virtual void printError() {
		cout << "errTooSmallException size: " << m_size << endl;
	}
};
Vector::Vector(int len){
	if(len < 0){
		throw errNegativeException(len);
	}else if(len == 0){
		throw errZeroException(len);
	}else if(len > 1000){
		throw errTooBigException(len);
	}else if(len < 10){
		throw errTooSmallException(len);
	}

	m_len = len;
	m_base = new int[len];
}

Vector::Vector(const Vector& object)
{
}

int Vector::getLength()
{
	return m_len;
}

int& Vector::operator[](int index)
{
	// TODO: 在此处插入 return 语句
	return m_base[index];
}

Vector::~Vector()
{
	if (m_base) delete[]m_base;
	m_len = 0;
}
int main() {
	try {
		Vector v(5);
	}
	catch (errSizeException& err) {
		err.printError();
	}
	/*catch (errNegativeException& error) {
		cout << "errNegativeException..." << endl;
	}
	catch (errZeroException &error) {
		cout << "errZeroException..." << endl;

	}
	catch (errTooBigException &error) {
		cout << "errTooBigException..." << endl;

	}
	catch (errTooSmallException &error) {
		cout << "errTooSmallException..." << endl;

	}*/
	/*for (int i = 0; i < v.getLength(); i++) {
		v[i] = i + 10;
		printf("v[i]: %d\n", v[i]);
	}*/
}

标准程序库异常


在这里插入图片描述

#include <iostream>
#include <exception>
#include <stdexcept>

using namespace std;

class Student {
public:
	Student(int age) {
		if (age > 249) {
			throw out_of_range("年龄太大了,你是外星人吗?");
		}
		m_age = age;
		m_space = new int[1024 * 1024*100];
	}
private:
	int m_age;
	int* m_space;
};

int  main() {
	try {
		for(int i=1;i<1024;i++)
			Student * xiao6lang = new Student(18);
	}
	catch (out_of_range &e) {
		cout << "捕捉到一只异常:" << e.what() << endl;
	}
	catch (bad_alloc& e) {
		cout << "捕捉到动态内存分配的异常:" << e.what() << endl;
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值