• 条款08:别让异常逃离析构函数


    问题:如果一个类的析构函数必须执行一个动作,而该动作可能会在失败时抛出异常,该怎么办?举个例子,假设使用过一个class负责数据库连接:

    class DBConnection
    {
    public:
    	...
    	static DBConnection create();	//此函数返回DBConnection对象
    
    	void close();			//关闭联机;失败则抛出异常
    };
    

    一个较佳策略是创建一个用来管理DBConnection资源的DBConn类,DBConn类自己提供一个close函数,因而赋予客户一个机会得益处理“因该操作而发生的异常”。DBConn也可以追踪其所管理的DBConnection是否已被关闭,若没有被关闭,则由DBConn的析构函数关闭它。这可防止遗失数据连接。然而如果DBConnection析构函数调用close失败,则可使用“强制结束程序”或“吞下异常”的方法:

    class DBConn
    {
    public:
    	DBConn();
    	~DBConn();
    
    	void close();
    private:
    	DBConnection db;
    	bool closed;
    };
    
    DBConn::DBConn()
    {
    }
    
    DBConn::~DBConn()
    {
    	if(!closed)
    	{
    		try
    		{
    			db.close();          //关闭连接
    		}
    		catch(...)                //如果关闭动作失败
    		{
    			写日志,记下对close的调用失败;  //记录下来并结束程序
    			...                //或者吞下异常;
    		}
    	}
    }
    
    void DBConn::close()		//供客户使用的新函数
    {
    	db.close();
    	closed = true;
    }
    

      

    如果某个操作可能在失败时抛出异常,而又存在某种需要必须处理该异常,那么这个异常必须来自析构函数以外的某个函数。因为析构函数抛出异常及时危险,总会带来“过早结束程序”或“发生不明确行为”的风险。

    请牢记:

    1、析构函数绝对不要抛出异常。如果一个被析构函数调用的函数可能抛出异常,析构函数应该捕获异常,然后吞下它们或结束程序。

    2、如果客户需要对某个操作函数进行运行期间抛出的异常做出反应,那么class应该提供一个普通函数(而非在析构函数中)执行操作。

     

  • 相关阅读:
    正则表达式和re模块
    面向对象基础
    面向对象高级
    网络编程
    collectiontimeossysjson模块
    继承
    封装
    我在吃饭
    111
    关于羽毛球拍
  • 原文地址:https://www.cnblogs.com/lwenwen/p/3468314.html
Copyright © 2020-2023  润新知