《Effective C++》条款8:关于析构函数异常捕捉的问题

本章节主要描述了析构函数异常捕捉的问题;

 

对于C++来说,有一条重要的异常捕捉规定:所以异常都可以抛出,但是不可以在析构函数内进行传播;

所以对于析构函数,一定要注意异常问题,要么捕捉,要么强行结束;

 

但是由于程序强制结束并不科学,所以一边采用捕捉的方式来进行处理;

但是一旦出现异常,必定意味着程序的运行出现了问题,往往最好的办法还是先用普通函数判断,最后在析构函数进行异常捕捉;

 

对于典型的案例,有数据库连接的问题;

class DBConnection {
public:
	static DBConnection create();
	void close();
};

class DBConn {
public:
	~DBConn() {
		db.close();
	}
private:
	DBConnection db;
};

如上所示,典型的数据库连接问题,其中DBConnection为一个连接类,DBConn为控制类,控制DBConnection的连接和释放;

但是存在问题的是,db.close()可能会调用失败,所以根据析构函数异常捕捉原则,我们采用两种方法进行;

 

使用abort()来解决:

class DBConn {
public:
	~DBConn() {
		db.close();
		std::abort();
	}
private:
	DBConnection db;
};

abort()的功能在于,如果抛出异常,不等异常传播,直接中断和结束所有程序运行;

这种方法比较无脑,违反了一般的程序逻辑控制思维;

 

使用try-catch来进行异常抓取:

class DBConn {
public:
	~DBConn() {
		try {
			db.close();
		}
		catch(exception){
			//对log日志进行记录,并且进行相关操作;
		}
	}
private:
	DBConnection db;
};

类似的操作有点像JAVA中的操作,抓取异常并且进行处理;


 

个人疑惑点:

对于书中的一点意见不太理解,try_catch完全可以在catch中对后续行为做出定义,为什么不能进行补救措施?


 

 

也可以对接口进行优化,采用“双保险”措施:

书中给出的案例是采用两次操作判定来减少这类情况的产生;

例如,对于database的连接,完全可以先关一次,最后析构函数再关一次;

class DBConn {
public:
	void close() {
		db.close();
		closed = true;
	}
	~DBConn() {
		if (!closed) {
			try {
				db.close();
			}
			catch (exception) {
				//继续log日志记录;
			}
		}
	}
private:
	DBConnection db;
	bool closed;
};

s

针对于析构函数异常的捕捉,可以“对于析构函数中可能出现异常的操作,先定义普通成员函数进行操作,而后在析构函数中进行tray-catch二次判断”

posted @ 2020-12-03 21:20  暮云林凌  阅读(194)  评论(0)    收藏  举报