c++11:异常

目录

c++异常与c传统处理错误的区别

c语言处理错误的方式

c++处理错误的方式

异常的抛出和处理

demo

异常的重新抛出

demo

异常安全

noexcept   

自定义异常体系


c++舍弃了c语言处理错误的方式,引入了异常来处理错误。

c++异常与c传统处理错误的区别

c语言处理错误的方式

1.暴力的终止程序,如assert终止程序。

2.返回错误码。

c++处理错误的方式

1.触发异常,将异常抛出。

2.捕捉异常,执行异常处理。

相比c语言,c++的处理更柔和,出错了程序也会照常执行,但是执行流会直接跳转到,异常处理的代码块。

异常的抛出和处理

throw:抛出异常,异常可以是任意的类型。

try:捕捉try代码块内抛出的异常

catch:代码块内是处理异常的,catch() 括号内是捕捉异常的类型

注意:

1.异常捕捉的规则是最近,匹配的catch。

2.异常如果到了main函数中还没有被捕获,程序就会直接终止。

3.通常会在最后加上catch(...),catch(...)可以捕获任意异常,这个主要就是增强代码的健壮性,防止,漏捕获异常,导致程序终止。

4.当异常出发throw之后的代码不会在继续执行,执行流跳转到,与抛出类型相同最近的catch代码块。

demo

简单的除零错误

#include<iostream>
using namespace std;

double Division(int a, int b)
{
	// 当b == 0时抛出异常
	if (b == 0)
	{
		throw "Division by zero condition!";//抛出了一个cosnt char*的异常
		cout << "~~~~~~~~~~~~~~" << endl;
	}
	else
		return ((double)a / (double)b);
}

int main()
{
	try 
	{
		Division(1,2);
		Division(1,0);
	}
	catch (const char * message)//这个catch只能捕捉const char*的异常
	{
		cout << message << endl;
	}
	catch (...)//捕捉任意的异常
	{
		cout<<"unknown execption" << endl;
	}
	cout << "-------------------" << endl;
	return 0;
}

异常的重新抛出

当异常抛出的时候,执行流回跳转,这时候就出现一个问题,在抛出异常之前动态开辟了一块空间,但是我这块空间还没来得及释放,但是执行流已经跳走了,这就会导致资源的泄露。

这种情况需要将异常处理之后,重新抛出,更好的办法就是使用智能指针,使用对象管理资源。

demo

#include<iostream>
using namespace std;

double Division(int a, int b)
{
	// 当b == 0时抛出异常
	if (b == 0)
	{
		throw "Division by zero condition!";
		cout << "~~~~~~~~~~~~~~" << endl; //没有被打印
	}
	else
		return ((double)a / (double)b);
}

void Func()
{
	int* arry = new int[5];

	try
	{
		int len, time;
		cin >> len >> time;
		cout << Division(len, time) << endl;

	}
	catch (...)
	{
		delete[] arry;
		cout << "already delete" << endl;
		throw;
	}
	delete[] arry;
}

int main()
{
	
	try
	{
		Func();

	}
	catch (const char * message)
	{
		cout << message << endl;
	}
	catch (...)
	{
		cout<<"unknown execption" << endl;
	}
	//cout << "-------------------" << endl;
	return 0;
}

异常安全

有一些的函数是不可以抛异常的,就像构造函数和析构函数。

构造函数通常用来初始化对象,如果初始化到一半,抛异常执行流跳走,会产生一个只初始化一半的怪物,会引起更多的异常

构造函数通常用来清理资源,如果抛异常执行流跳走,会导致有的资源未被释放,导致资源泄露。

noexcept   

由noexcept 修饰的函数,不会抛出异常。

自定义异常体系

在实际开发中,都会有一个异常的体系,因为如果异常是随便抛出的,那可就坏事了,程序员A抛出了一个int,程序员B抛出了一个char*。

异常是不能随便抛的,是要有严格规范的。

通常都会使用多态,catch基类可以捕捉抛出的派生类的异常。

使用基类调用,what这个虚函数。

class Exception
{
public:
 Exception(const string& errmsg, int id)
 :_errmsg(errmsg)
 ,_id(id)
 {}

 virtual string what() const
 {
 return _errmsg;
 }

protected:
 string _errmsg;
 int _id;
};

class SqlException : public Exception
{
public:
 SqlException(const string& errmsg, int id, const string& sql)
 :Exception(errmsg, id)
 , _sql(sql)
 {}

 virtual string what() const
 {
 string str = "SqlException:";
 str += _errmsg;
 str += "->";
 str += _sql;
 return str;
 }

private:
 const string _sql;
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值