C++异常机制

C++异常机制

异常处理的初步使用

我们将可能导致异常的代码块用try语句块包含起来,我们称之为安全段,然后在其后捕获可能出现的异常。

注意:必须捕获至少一个异常,不然会出错。如果异常被捕获一次,除非再次抛出,不然就不会再被捕获了,尽管捕获代码里可能什么都没有做。一旦抛出异常,程序将会立即跳转到try语句块所对应的catch捕获代码,不会再执行try语句块剩下的语句。

#include <iostream>
#include <string>
using namespace std;
//指定所有可能抛出的类型
void fun1(const char* dest, const char* res)throw(int,string*,float) {
	FILE *f1, *f2;
	f1 = f2 = NULL;
	fopen_s(&f1, res, "rb");//二进制只读
	if (f1 == NULL) {
		throw new string("源文件打开失败!");
	}
	fopen_s(&f2, dest, "wb");//二进制只写
	if (f2 == NULL) {
		throw new string("目标文件打开失败!");
	}
	char buffer[64];
	int readsize, writesize;
	while (readsize = fread(buffer, 1, 64, f1) > 0) {//有数据读出
		writesize = fwrite(buffer, 1, 64, f2);
		if (readsize != writesize) {
			throw new string("读取文件失败!");
		}
	}
	fclose(f1);
	fclose(f2);
}
void fun2(const char* dest, const char* res) {
	try {
		fun1(dest, res);
	}
	catch(...) {//捕获任何类型的异常
		throw;
		cout << "fun2异常捕获" << endl;
	}
}
int main(void) {
	try {
		cout << "异常捕获准备" << endl;
		fun2("dest.txt", "res.txt");
		cout << "异常捕获完成" << endl;
	}
	catch (int error) {
		
	}
	catch (string* error) {
		printf("异常:%s", error->c_str());
	}
	catch (float error) {

	}
	return 0;
}

异常处理接口声明

  1. 在函数声明中列出所有可能抛出的异常类型
  2. 如果没有包含异常接口声明,默认可以抛出任何类型
  3. 不可以抛出异常接口声明中的类型,否则会报错
  4. 如果不想抛出任何类型,可以直接定义为空
void fun1(const char* dest,const char* res)throw(){}

异常类型的生命周期

一般来说,局部变量的生命周期会在离开函数之后马上析构,但匿名对象可以和catch中的参数一起在catch语句块结束后析构

注意事项

  1. throw类类型,最佳的方式就是使用引用类型捕获,抛出匿名对象。
  2. 如果是动态分配的内存,直接返回指针,但是要记得delete。
  3. 返回字符串的本质其实就是返回一个指针,其实也属于值传递。
  4. 引用和普通的形参类型不能共存,这点和函数调用是一样的。

异常类

异常也可以算做一个类,也就是说,我们可以直接定义一个错误的基类,然后从安全段中返回一个具体错误的子类。再从catch中捕获基类的引用,或者基类的指针,以此完成多态。

#pragma once
#include <iostream>
class abnormal {
public:
	abnormal(int size) { this->size = size; }
	virtual ~abnormal() {};
	virtual void desc()const = 0;
protected:
	int size;
};
class negativeabnormal :public abnormal {
public:
	negativeabnormal(int size) :abnormal(size) {}
	~negativeabnormal() {};
	void desc()const override {
		std::cout << "negativeabnormal!\nsize:" << size << std::endl;
	}
};
class boundaryabnormal :public abnormal {
public:
	boundaryabnormal(int size) :abnormal(size) {}
	~boundaryabnormal() {};
	void desc()const override {
		std::cout << "boundaryabnormal!\nsize:" << size << std::endl;
	}
};

在安全段中返回子类的对象,然后用基类引用来捕获就行了

template<typename T>
Vector<T>::Vector(int size) {
	/*if (size > 0) {
		this->size = size;
	}
	else {
		this->size = 64;
	}
	arr = new T[this->size];*/
	if (size < 0) {
		this->size = 64;
		throw negativeabnormal(size);
	}
	else if (size > BOUNDARY) {
		this->size = BOUNDARY;
		throw boundaryabnormal(size);
	}
	else {
		this->size = size;
	}
	arr = new T[this->size];
}


	try {//安全段
		Vector<int> v1(100);
		for (int i = 0; i != 10; ++i) {
			v1[i] = i + 1;
		}
		for (int i = 0; i != 10; ++i) {
			cout << v1[i] << " ";
		}
	}
	catch (const abnormal& object) {
		object.desc();
		cout << endl;
	}

标准库里的异常类

标准库里也定义了一些异常类供我们使用,比较常见的有bad_alloc和out_of_range子类的,其中bad_alloc由系统在分配空间失败时自动调用。记得要包含对应的头文件exception和stdexcept

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值