C++ 异常的语法,栈解旋和接口声明,异常的生命周期、层次结构、标准异常库

1. 基本语法

通过异常可以使原本会发生宕机的异常被特殊处理。程序给出提示,但程序不崩溃。

  1. 发生异常之后,是跨函数的
  2. 接收异常之后,可以不处理,再抛出
  3. catch异常时,按照类型进行catch
  4. 异常捕捉严格按照类型匹配
#include <iostream>
using namespace std;

//1 发生异常之后,是跨函数的
//2 接收异常之后,可以不处理,再抛出
//3 catch异常时,按照类型进行catch
//4 异常捕捉严格按照类型匹配

//异常的 栈解旋 就是在抛出异常时,调用相应的析构函数。

void divide(int x, int y)
{
	if (y == 0)
	{
		throw x;//抛出int类型异常
	}
	cout << "divide result: " << x / y << endl;
}

//发生异常之后,是跨函数的
void myDivide(int x, int y)
{
	try
	{
		divide(x, y);
	}
	catch (...)
	{
		cout << "我接收了divide的异常,不处理往上抛" << endl;
		throw;
	}
}

int main()
{
	try
	{
		divide(10, 2);
		//divide(100, 0);

		myDivide(20, 0);
	}
	catch (const int e)
	{
		cout << e << " is divided by 0!" << endl;
	}
	catch (...)
	{
		cout << "其他未知类型异常" << endl;
	}

	return 0;
}

2. 栈解旋和异常接口声明

#include <iostream>
using namespace std;

class Test3
{
public:
	Test3(int a = 0, int b = 0)
	{
		this->a = a;
		this->b = b;
		cout << "构造函数" << endl;
	}
	~Test3()
	{
		cout << "析构函数" << endl;
	}

private:
	int a;
	int b;
};

//不写,抛出所有类型异常
void myDivide()
{
	Test3 t1(1, 2), t2(3, 4);
	cout << "myDide即将发生异常" << endl;
	throw 1;//抛出异常时,会析构t1,t2,这就是栈解旋,这样可以防止程序崩溃
}

//抛出已写类型的异常
void myDivide2() throw(int, char, char*)
{
	Test3 t1(1, 2), t2(3, 4);
	cout << "myDide2即将发生异常" << endl;
	throw 1;
}

//不抛出任何类型的异常
void myDivide3() throw()
{
	Test3 t1(1, 2), t2(3, 4);
	cout << "myDide3即将发生异常" << endl;
	throw 1;
}

int main()
{
	try
	{
		//myDivide();//抛出异常时,程序结束
		myDivide2();
		//myDivide3();

	}
	catch (int a)
	{
		cout << "int 型异常" << endl;
	}

	return 0;
}

3. 异常的生命周期

#define  _CRT_SECURE_NO_WARNINGS 
#include <iostream>

using namespace std;

//使用异常的方式进行处理


void my_strcpy1(char *dst, char *from) {
	if (dst == NULL) {
		throw 1; //1 代表目的地址有问题
	}
	else if (from == NULL) {
		throw 2; //2 代表源地址有问题
	}

	if (*from == 'a') {
		throw 3; //代表copy过程出现问题
	}


	while (*from != '\0') {
		*dst = *from;
		dst++;
		from++;
	}
	*dst = '\0';
}


void my_strcpy2(char* dst, char *from) 
{
	if (dst == NULL) {
		throw "目的地址有问题"; //1 代表目的地址有问题
	}
	else if (from == NULL) {
		throw "源地址有问题"; //2 代表源地址有问题
	}

	if (*from == 'a') {
		throw "copy过程出现问题"; //代表copy过程出现问题
	}


	while (*from != '\0') {
		*dst = *from;
		dst++;
		from++;
	}
	*dst = '\0';
}

//目的地址有问题的异常类型
class BadDstAddrType{};
class BadSrcAddrType{};
class BadProcessAddrType{
public:
	BadProcessAddrType()
	{
		cout << "BadProcessAddrType().." << endl;
	}
	BadProcessAddrType(const BadProcessAddrType & obj)
	{
		cout << "BadProcessAddrType(const BadProcessAddrType &)..." << endl;
	}
	void print() {
		cout << "copy过程出现了异常" << endl;
	}
	~BadProcessAddrType(){
		cout << "~BadProcessAddrType()..." << endl;
	}
};

void my_strcpy3(char *dst, char *from)
{
	if (dst == NULL) {
		throw BadDstAddrType(); //1 代表目的地址有问题
	}
	else if (from == NULL) {
		throw BadSrcAddrType(); //2 代表源地址有问题
	}

	if (*from == 'a') {
		//throw new BadProcessAddrType(); //在抛出这个BadProcessAddrType() 会创建一个匿名对象 
		throw BadProcessAddrType();
	}


	while (*from != '\0') {
		*dst = *from;
		dst++;
		from++;
	}
	*dst = '\0';
}

int main(void)
{
	char buf1[] = "a234567";
	char buf2[128] = { 0 };

	try {
		my_strcpy3(buf2, buf1);
	}
	catch (int e)
	{
		cout << "捕获到异常代码e = " << e << endl;
	}
	catch (char *e)
	{
		cout << "捕获到char*类型异常e = " << e << endl;
	}
	//catch (BadProcessAddrType e) { //BadProcessAddrType e = 匿名对象temp //在捕获的时候,如果用一个元素捕获
													//会发生拷贝构造,异常对象e和被抛出来的匿名对象不是一个对象
													//会有深拷贝和浅拷贝的风险
//		cout << "捕获到了BadProcessAddrType 异常类型e  " << endl;
//		e.print();
//	}
	catch (BadProcessAddrType *e) { //此时那个匿名对象已经被释放了,e是一个野指针
		cout << "捕获到了BadProcessAddrType* 异常类型e" << endl;
		delete e; //如果抛出的异常类型是new出来的,需要显示的delete掉
	}
	catch (BadProcessAddrType &e) { //1 普通元素类型的异常捕获,不能够跟 引用捕获同时存在。
		cout << "捕获到了 BadProcessAddrType & 异常类型" << endl;
		//编译器发现使用引用捕获的,那么不会立刻释放掉匿名对象, 而是在异常处理完之后,才把e释放。
		//可以理解为 BadProcessAddrType &e = BadProcessAddrType()
	}
	catch(...) 
	{
		cout << "捕获到未知异常" << endl;
	}
}

#if 0
int my_strcpy(char *dst, char *from)
{
	if (dst == NULL) {
		return 1; //1 代表目的地址有问题
	}
	else if (from == NULL) {
		return 2; //2 代表源地址有问题
	}

	if (*from == 'a') {
		return 3; //代表copy过程出现问题
	}


	while (*from != '\0') {
		*dst = *from;
		dst++;
		from++;
	}
	*dst = '\0';

	return 0;
}

//传统的捕获错误方法
int main(void)
{
	char buf1[] = "a234567";
	char buf2[128] = { 0};
	int ret = 0;

	ret = my_strcpy(buf2, buf1);
	if (ret != 0) {
		switch (ret)
		{
		case 1:
			cout << "目的地址有问题" << endl;
			break;
		case 2:
			cout << "原地址有问题" << endl;

			break;
		case 3:
			cout << "拷贝过程有问题" << endl;

			break;
		default:
			break;
		}
	}
	else {
		cout << "buf2 = " << buf2 << endl;
	}

	
	return 0;
}
#endif

4. 异常的层次结构

#define  _CRT_SECURE_NO_WARNINGS 
#include <iostream>

using namespace std;

class eSize
{
public:
	eSize(int len)
	{
		this->len = len;
	}
	virtual void printErr() {
		cout << "eSize error: len = " << len << endl;
	}
protected:
	int len;
};

class eNagtive :public eSize
{
public:
	eNagtive(int len): eSize(len) {
	}

	virtual void printErr()
	{
		cout << "eNagtive error: len = " << len << endl;
	}
};

class eZero :public eSize
{
public:
	eZero(int len) :eSize(len) {

	}

	virtual void printErr()
	{
		cout << "eZero error: len = " << len << endl;
	}
};

class eTooBig :public eSize
{
public:
	eTooBig(int len) :eSize(len) {

	}

	virtual void printErr()
	{
		cout << "eTooBig error: len = " << len << endl;
	}
};

class eTooSmall :public eSize
{
public:
	eTooSmall(int len) :eSize(len) {

	}

	virtual void printErr()
	{
		cout << "eTooSmall error: len = " << len << endl;
	}
};

class MyArray
{
public:
	MyArray(int len)
	{
		if (len < 0) {
			throw eNagtive(len);
		}
		else if (len == 0) {
			throw eZero(len);
		}
		else if (len > 1000) {
			throw eTooBig(len);
		}
		else if (len < 10) {
			throw eTooSmall(len);
		}
		this->len = len;
		this->space = new int[len];
	}

	int & operator[](int index)
	{
		return this->space[index];
	}

	int getLen()
	{
		return this->len;
	}

	~MyArray() {
		if (this->space != NULL) {
			delete[] this->space;
			this->space = NULL;
			this->len = 0;
		}
	}
private:
	int len;//元素的个数
	int *space;
};

int main(void)
{
	try {
		MyArray array(3);

		for (int i = 0; i < array.getLen(); i++) {
			array[i] = i + 1;
		}

		for (int i = 0; i < array.getLen(); i++) {
			cout << array[i] << endl;
		}
	}
	catch (eSize &e) //eSize &e = eNagtive(len);
	{
		cout << "捕获到异常" << endl;
		e.printErr();//发生多态
	}

#if 0
	catch (eNagtive &e)
	{
		cout << "捕获到eNagive 异常" << endl;
		e.printErr();
	}
	catch (eZero &e) {
		cout << "捕获到eZero 异常" << endl;
		e.printErr();
	}
	catch (eTooBig &e) {
		cout << "捕获到eTooBig 异常" << endl;
		e.printErr();
	}
	catch (eTooSmall &e) {
		cout << "捕获到eTooSmall 异常" << endl;
		e.printErr();
	}
	catch (...)
	{
		cout << "捕获到未知异常" << endl;
	}
#endif

	
	return 0;
}

5. 标准异常库

#define  _CRT_SECURE_NO_WARNINGS 
#include <iostream>
#include <stdexcept>
#include <string>

using namespace std;

//自定义的MyException 也加入标准的异常库
class MyException :public exception
{
public:
	MyException(char *str) {
		this->m_s = str;
	}
	virtual const char *what() const{
		cout << "MyException 的异常" << endl;
		return this->m_s;
	}
private:
	char *m_s;
};

class Teacher
{
public:
	Teacher(string name, int id)
	{
		this->name = name;
		if (id > 100) {
			string str = "id 超出范围";
			throw out_of_range(str);
		}
		this->id = id;
	}
private:
	int id;
	string name;
};

int main(void)
{
	try
	{
		Teacher t1("zhangsan", 10001);
	}
	catch (exception &e)
	{
		cout << e.what() << endl;
	}
	

	try {
		throw MyException("aaaa");

	}
	catch (exception &e){
		cout << e.what() << endl;
	}
	
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

banjitino

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值