STL5-异常

博客主要围绕C++异常处理展开,提到异常可跨函数且必须处理,还介绍了栈解旋、异常接口声明、异常类型、异常生命周期等内容,给出了C++异常库举例,并阐述了继承在异常中的应用。

异常可以跨函数

异常必须处理

1、

#include<iostream>
using namespace std;
//c++异常机制 跨函数
//c++异常必须处理 不能留,否则报错
int divided(int x, int y)
{
	if (y == 0)
		throw y;  //抛异常
	return (x / y);
}
void test01()
{
	int x = 10, y = 0;
	//试着去捕获异常
	try
	{
		divided(x, y);
	}
	catch (int y)  //异常是根据类型进行匹配
	{
		cout << "除数为" << y <<"!"<< endl;
	}
}

void CallDivide(int x, int y)
{
	divided(x, y);
}
//如果异常抛到顶层,还没有处理这个时候程序后挂掉terminal()
//a调用b,b调用c,c调用d函数 a-->b-->c-->d
//d抛出异常,c没有处理,则继续给b,b还没有处理给a,则异常给a,a处理(catch)即可。若a还不处理,则报错,程序挂掉
void test02() {
	try
	{
		CallDivide(1, 0);
	}
	catch (int e)
	{
		cout << "除数为" << e << endl;
	}
}
int main()
{
	test01();
	cout << "------------------" << endl;
	test02();
}

2、栈解旋

#include<iostream>
using namespace std;

class person {
public:
	person()
	{
		cout << "对象构建" << endl;
	}
	~person()
	{
		cout << "对象析构" << endl;
	}

};

int divide(int x, int y)
{
	person p1, p2;
	if (y == 0)
		throw y;
	return x / y;
}
//栈解旋:try catch中调用函数发生异常时,函数内的局部变量会被析构掉
void test01()
{
	try {
		divide(10, 0);
	}
	catch (int e)
	{
		cout << "异常捕获!" << endl;
	}
}

int main()
{
	test01();
	return 0;
}

3、异常接口的声明

#include<iostream>
using namespace std;
//这个函数只能抛出int,float,char三种类型异常,抛出其他报错
void func() throw(int, float, char)
{
	throw "abc";
}
//不能抛出任何类型异常
void func02() throw()
{
	throw - 1;
}
//抛出任何类型异常
void func03()
{
	throw - 2;
}
int main()
{
	try {
		func();
	}
	catch (char* str)
	{
		cout << str << endl;
	}
	catch (int e)
	{
		cout << "异常!" << endl;
	}
	catch (...)  //...代表所有异常类型
	{
		cout << "捕获所有未知类型异常" << endl;
	}
}

 

4、异常类型

#include<iostream>
using namespace std;

void func01(){
	throw 1;  //抛出int类型异常
}
void func02() {
	throw "exception";  //抛出char*类型异常
}
class MyException {
public:
	MyException(char* str) {
		error = new char[strlen(str) + 1];
		strcpy(error, str);
	}
	void what() {
		cout << error << endl;
	}
	MyException(const MyException& ex){    //拷贝构造
		this->error = new char[strlen(ex.error) + 1];
		strcpy(this->error, ex.error);
	}
	MyException& operator=(const MyException& ex) {  //等于构造
		if (this->error != NULL)
		{
			delete[] this->error;
			this->error = NULL;
		}
		this->error = new char[strlen(ex.error) + 1];
		strcpy(this->error, ex.error);
	}
	MyException()
	{
		if (error != NULL)
		{
			delete[] error;
		}
	}
public:
	char* error;
};
void func03() {
	throw MyException("我刚写的异常!");
}
void test01(){
	try {
		func01();
	}
	catch (int e) {
		cout << "异常捕获!" << endl;
	}
//----------------------------------------
	try {
		func02();
	}
	catch (char* e) {
		cout << "异常捕获!" << endl;
	}
//-----------------------------------------
	try {
		func03();
	}
	catch (MyException e) {
		e.what();
	}
}

int main()
{
	MyException e1=MyException("dd");  //拷贝构造
	MyException e2 = e1;  //等于构造
	test01();
	return 0;
}

运行结果: 

5、异常生命周期

#include<iostream>
using namespace std;

class MyException {
public:
	MyException() {
		cout << "构造函数" << endl;
	}
	
	MyException(const MyException& ex) {    //拷贝构造
		cout << "拷贝构造函数" << endl;
	}
	~MyException() {
		cout << "析构函数" << endl;
	}
	
};
void func() {
	//throw MyException();  //创建匿名对象,调用构造函数
	//throw &(MyException());  //创建匿名对象,调用构造函数
	throw new MyException();
}
void test01() {
	//普通类型元素 引用 指针
	//普通类型元素 catch处理完后就析构
	//引用的话 不用调用拷贝构造 catch处理完后就析构
	//指针的话,需要new一个异常,否则在捕捉异常前就已经析构
	try {
		func();
	}
	//catch (MyException e) { //用MyException元素接,相当于将上面的MyException()拷贝一份传给e,调用拷贝构造
	//	cout << "异常捕获" << endl;
	//}
	//catch (MyException& e) { //用MyException元素接,相当于将上面的MyException()拷贝一份传给e,调用拷贝构造
	//	cout << "异常捕获" << endl;
	//}
	catch (MyException* e) { //用MyException元素接,相当于将上面的MyException()拷贝一份传给e,调用拷贝构造
		cout << "异常捕获" << endl;
		delete e;
	}
}

int main()
{
	test01();
	return 0;
}

运行结果: 

6、c++异常库举例

#include<iostream>
#include<stdexcept>
using namespace std;
 
class Person {
public:
	Person() {
		mAge = 0;
	}
	void setAge(int age)
	{
		if (age < 0 || age>100) {
			throw out_of_range("年龄在0-100之间!");
		}
		this->mAge = age;
	}
public:
	int mAge;
};
void test01(){
	Person p;
	try {
		p.setAge(1000);
	}
	catch (out_of_range e) {
		cout << e.what() << endl;
	}
	catch (exception e) {
		cout << e.what() << endl;
	}
}


class MyOutOfRange : public exception {
public:
	MyOutOfRange(char* error) {
		pError = new char[strlen(error) + 1];
		strcpy(pError, error);
	}
	virtual char const* what() const {
		return pError;
	}
	MyOutOfRange() {
		if (pError != NULL) {
			delete[] pError;
		}
	}
public:
	char* pError;
};
void func02() {
	throw MyOutOfRange("我自己抛出的异常");
}
void test02() {
	try {
		func02();
	}
	catch (exception& e) {
		cout << e.what() << endl;
	}
}
int main() {
	test01();
	test02();
	return 0;
}

运行结果: 

7、继承在异常中的应用

#include<iostream>
using namespace std;

//异常基类
class BaseMyException {
public:
	virtual void what()=0;
	virtual ~BaseMyException() {};
};
class TargetSpaceNullException :public BaseMyException {
public:
	virtual void what() {
		cout << "目标空间为空!" << endl;
	}
	~TargetSpaceNullException(){}
};
class SourceSpaceNullException :public BaseMyException {
public:
	virtual void what() {
		cout << "源空间为空" << endl;
	}
	~SourceSpaceNullException() {}
};

void copy_str(char* target, char* source){
	if (target == NULL){
		//cout << "目标空间为空" << endl;
		throw TargetSpaceNullException();
		return;
	}
	if (source == NULL) {
		throw SourceSpaceNullException();
		//cout << "源空间为空" << endl;
		return;
	}
	int len = strlen(source)+1;
	while (*source != '\0') {
		*target = *source;
		source++;
		target++;
	}
}


int main()
{
	char* source = "abcdefg";
	char buf[1024] = { 0 };
	cout << "copy" << endl;
	try {
		copy_str(NULL, source);
	}
	catch (BaseMyException& e) {
		e.what();
	}
	
	cout << buf << endl;
	return 0;
}

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

chde2Wang

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

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

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

打赏作者

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

抵扣说明:

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

余额充值