【C++】异常处理之throw、catch、try、局部资源管理、标准异常库

一、抛出异常

异常处理机制两个主要成分:

  1. 异常的鉴定与发出;
  2. 异常的处理方式。

C++通过throw表达式产生异常:

cpp 复制代码
inline void Triangular_iterator::
check_integrity()
{
	if(_index>=Triangular::max_elems)
	{
		throw iterator_overflow(_index, Triangular::_max_elems);
		if(_index >= Triangular::elems.size())
		{
			Triangular::gen_elemts(_index+1);
		}
	}
}

//换个方式:明确指出被抛出的对象名称
if(_index>=Triangular::max_elems)
{
	iterator_overflow ex(_index,Triangular::_max_elems);
	throw ex;
}

异常对象

最简单的异常对象可以设计为:整数或字符串:

cpp 复制代码
throw 42;
throw "panic:no buffer!";

异常类

大部分时候,被抛出的异常都属于特定的异常类:

cpp 复制代码
class iterator_overflow{
public:
	iterator_overflow(int index,int max):_index(index),_max(max){}

	int index(){return _index;}
	int max(){return _max;}
	
	void what_happened(ostream &os=cerr)
	{
		os<<"Internal error:current index "<<_index
		  <<" exceeds maximum bound: "<<_max;
	}
	
private:
	int _index;
	int _max;
};

二、捕获异常

catch子句

由三部分组成:

  1. 关键字catch;
  2. 小括号内的一个类型或对象;
  3. 大括号内的一组语句(用以处理异常)。
cpp 复制代码
extern void log_message(const char*);
extern string err_messages[];
extern ostream log_file;

bool some_function()
{
	bool status = true;
	
	catch(int errno)
	{
		log_message(err_messages[errno];
		status = false;
	}
	
	catch(const char *str)
	{
		log_message(str);
		status = false;
	}
	
	catch(iterator_overfloww &iof)
	{
		iof.what_happened(log_file);
		status = false;
	}
	
	return status;
}

//逐个处理
throw 42;
throw "panic:no buffer!";
throw iterator_overflow(_index,Triangular::_max_elems);

有时候我们可能无法完成异常的完整处理。在记录信息之外,我们或许需要重新抛出异常,以寻求其他catch子句的协助:

cpp 复制代码
catch(iterator_overflow &iof)
{
	log_message(iof.what_happened());
	
	//重新抛出异常,另一个catch子句来接手处理
	throw;//甚至只可以出现在catch子句中
}

捕获任何类型的异常:catch(...)

cpp 复制代码
catch(...)
{
	log_message("exception of unknown type");
	//清理后退出
}

三、提炼异常

try块

  • try语句块用来处理异常,try语句块以关键字try开始,以一个或多个catch子句结束,try语句块中代码抛出的异常通常会被某个catch子句处理;
  • 当函数的try块发生某个异常,但没有相应的catch子句将它捕获,此函数便会转到terminate的标准库函数,terminate会终止当前进程的执行,由异常处理机制接管,沿着"函数调用链"一路回溯,搜寻符合条件的catch子句。
cpp 复制代码
bool has_elem(Triangular_iterator first, Triangular_iterator last, int elem)
{
	bool status = true;
	try
	{
		while(first != last)
		{
			if(*first == elem)
			{
				return status;
			}
			++first;
		}
	}
	catch(iterator_overflow &iof)
	{
		log_message(iof.what_happened());
		iog_message("check if iterators address same container");
	}
	//try块内的程序代码执行时,如果有任何异常抛出,
	//只捕获其中类型为iterator_overflow的异常。
	status = false;
	return status;
}

四、局部资源管理

函数执行之初所分配的资源不一定最终会被释放掉。

解决:资源管理的手法(在初始化阶段即进行资源请求)

cpp 复制代码
#include<memory>

void f()
{
	auto_ptr<int>p(new int);
	MutexLock m1(m);
	process(p);
	//p和m1的析构函数在此被悄悄调用
}

auto_ptr

标准类模板:自动删除通过new表达式分配的对象。

auto_ptr将*运算符和->运算符予以重载,方式类似迭代器类那样,我们得以像使用一般指针一样地使用auto_ptr对象:

cpp 复制代码
auto_ptr<string>aps(new string("vermeer"));
string *ps=new string("vermmer");
if((aps->size()==ps->size())&&(*aps==*ps))
//...

五、标准异常

参考:C++标准异常库、编写自己的异常类

自己编写的异常类继承给exception基类:

  • 所有的异常类都有一个what()方法,返回const char* 类型,描述异常信息;
  • 可被任何"打算捕获抽象基类exception"的程序代码所捕获。
相关推荐
油丶酸萝卜别吃3 小时前
utils.js 说明文档
开发语言·javascript·ecmascript
leisoo80976 小时前
100GBA股股票数据怎么存ClickHouseRedisMySQLJSON完整对比
大数据·linux·服务器·开发语言·python
不会代码的小猴7 小时前
21. 泛型编程上
开发语言·c++·笔记·算法
青瓦梦滋7 小时前
传输层UDP/TCP协议
linux·网络·c++·网络协议·tcp/ip·udp
一只旭宝8 小时前
细讲C加加【9】C++ std::function与std::bind详解|仿函数、绑定器、类成员绑定、占位符、成员偏移指针
开发语言·c++·算法
摇滚侠8 小时前
《SpringBoot 3:入门与应用实战》第 2 章 IOC 思想与实现 阅读笔记 1
spring boot·笔记·后端
蒸蒸yyyyzwd9 小时前
秋招不熟悉力扣学习笔记1
笔记·学习·leetcode
coder!mq10 小时前
说几个常见的语法糖?
java·开发语言·算法
gugucoding10 小时前
38. 【Java】Stream API(下):高级操作与性能
java·开发语言
Lhan.zzZ10 小时前
在 Visual Studio 2022 中打造可扩展的动态链接库模块:从零搭建到原理解析
开发语言·c++·visual studio