C++异常处理


C语言中错误的检测方法是 assert,这种方式对于错误处理几乎没有。当你拿到C语言的的 errno,对应去处理该错误。C++提供了一种新的异常处理方式, 将问题检测和问题处理相分离

关键字throw、try、catch

throw: 当问题出现时,程序会抛出一个异常。

catch: 在您想要处理问题的地方,通过异常处理程序捕获异常。 catch 关键字用于捕获异常,可以有多个catch进行捕获。

try: try 块中的代码标识将被激活的特定异常,它后面通常跟着一个或多个 catch 块。被选中的处理代码是调用链中与该对象类型匹配且离抛出异常位置最近的那一个。 例外;可以抛出的派生类对象,使用基类捕获。

catch(…)表示可以捕获任意没有对应类型的异常抛出。

最简单的异常使用实例。

#include <iostream>
using namespace std;

double Div(int x, int y)
{
	if (y == 0)
		throw "Div zero";
	else
		return x / y;
}

int main()
{
	int x = 10;
	int y = 0;
	double z = 0;
	try{
		z = Div(x, y);
	}
	catch (const char* str)
	{
		cout << str << endl;
	}
	catch (...)
	{
		cout << "Unknow Abnormal" << endl;
	}

	system("pause");
	return 0;
}

函数调用链中异常的栈展开规则

在编译阶段进行站展开查找栈内最近的捕获点。
在这里插入图片描述

异常说明

异常规格说明的目的是为了让函数使用者知道该函数可能抛出的异常有哪些。

1. 可以在函数的后面接throw(类型),列出这个函数可能抛掷的所有异常类型。
2. 函数的后面接throw(),表示函数不抛异常。
3. 若无异常接口声明,则此函数可以抛掷任何类型的异常。

void fun() throw(A,B,C,D);
//这里表示这个函数会抛出A/B/C/D中的某种类型的异常
void* operator new (std::size_t size) throw (std::bad_alloc);
// 这里表示这个函数只会抛出bad_alloc的异常
void* operator new (std::size_t size, void* ptr) throw();
// 这里表示这个函数不会抛出异常

异常再次抛出

有时候catch捕获了异常, 并不能对这个异常完全处理,需要外出调用函数进行再处理,就可以在将这个异常抛出。

void Func1()
{
	throw "error!!";
}

void Func2()
{
	int* array=new int[3];
	try{
		Func1();
	}
	catch (...)
	{
		delete [] array;
		throw ;//把捕获到的任意异常再次抛出
	}
	delete [] array;
}


int main()
{
	try{
		Func2();
	}
	catch (...)
	{
		cout << "Unknow abnormal" << endl;
	}
}

C++标准库的异常体系

C++ 提供了一系列标准的异常,定义在 exception 中,我们可以在程序中继承这个exception实现自己的异常类。下图是C++标准库的异常类,都是exception这个异常的继承类,所以使用中,可以都捕获exception。what这个多态实现的成员函数可以给出异常的描述。
在这里插入图片描述

#include<iostream>
#include<exception>
#include<vector>

using namespace std;

int main()
{
	try{
		vector<int> v(10, 5);
		// 这里越界会抛异常
		v.at(100) = 100;
	}
	catch (const exception& e) // 这里捕获父类对象就可以
	{
		cout << e.what() << endl;
	}
	catch (...)
	{
		cout << "Unkown Exception" << endl;
	}
	system("pause");
	return 0;
}
invalid vector<T> subscript
请按任意键继续. . .

C++异常处理的优缺点

缺点

1)C++没有垃圾回收机制,资源需要自己管理。C++中异常经常会导致资源泄漏的问题,比如在new和delete中抛出了异常,导致内存泄漏,在lock和unlock之间抛出了异常导致死锁。
2)异常会导致运行时出错抛异常就会乱跳。导致调试程序比较困难。
3)异常会有一些性能的开销。

优点

1)相比错误码的方式可以清晰准确的展示出错误的各种信息,这样可以帮助更好的定位程序的bug。
2)使用错误码,如果深层错误,需要层层返回,外出才能拿到错误码。
3)部分函数使用异常更好处理,比如T&operator[ ]这样的函数,如果pos越界了只能使用异常或者终止程序处理,没办法通过返回值表示错误。

异常其它特点

1)异常规范有两点:一、抛出异常类型都继承自一个基类。二、函数是否抛异常、抛什么异常,都使用 func()throw();的方式规范化。
2)构造函数中不能抛异常,抛异常可能导致对象定义不完整。析构函数不能抛异常,可能导致内存泄漏。

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值