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


    一、抛出异常

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

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

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

    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;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    异常对象

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

    throw 42;
    throw "panic:no buffer!";
    
    • 1
    • 2

    异常类

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

    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;
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    二、捕获异常

    catch子句

    由三部分组成:

    1. 关键字catch;
    2. 小括号内的一个类型或对象;
    3. 大括号内的一组语句(用以处理异常)。
    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);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

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

    catch(iterator_overflow &iof)
    {
    	log_message(iof.what_happened());
    	
    	//重新抛出异常,另一个catch子句来接手处理
    	throw;//甚至只可以出现在catch子句中
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

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

    catch(...)
    {
    	log_message("exception of unknown type");
    	//清理后退出
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    三、提炼异常

    try块

    • try语句块用来处理异常,try语句块以关键字try开始,以一个或多个catch子句结束,try语句块中代码抛出的异常通常会被某个catch子句处理;
    • 当函数的try块发生某个异常,但没有相应的catch子句将它捕获,此函数便会转到terminate的标准库函数,terminate会终止当前进程的执行,由异常处理机制接管,沿着“函数调用链”一路回溯,搜寻符合条件的catch子句。
    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;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    四、局部资源管理

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

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

    #include
    
    void f()
    {
    	auto_ptr<int>p(new int);
    	MutexLock m1(m);
    	process(p);
    	//p和m1的析构函数在此被悄悄调用
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    auto_ptr

    标准类模板:自动删除通过new表达式分配的对象。
    auto_ptr将*运算符和->运算符予以重载,方式类似迭代器类那样,我们得以像使用一般指针一样地使用auto_ptr对象:

    auto_ptr<string>aps(new string("vermeer"));
    string *ps=new string("vermmer");
    if((aps->size()==ps->size())&&(*aps==*ps))
    //...
    
    • 1
    • 2
    • 3
    • 4

    五、标准异常

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

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

    • 所有的异常类都有一个what()方法,返回const char* 类型,描述异常信息;
    • 可被任何“打算捕获抽象基类exception”的程序代码所捕获。
  • 相关阅读:
    ChatGPT追祖寻宗:GPT-1论文要点解读
    【LeetCode刷题-滑动窗口】-- 795.区间子数组个数
    Spring AOP使用指南: 强大的面向切面编程技术
    linux内的循环
    qt day
    Leetcode6238-统计构造好字符串的方案数
    RabbitMQ 如何避免消息重复消费?
    Python:用tkinter制做一个音乐下载小软件
    深度学习之wandb的基本使用
    工地渣土车清洗识别检测系统
  • 原文地址:https://blog.csdn.net/weixin_49347928/article/details/133801771