- 放掉析构函数中的异常可能会导致程序崩溃
class Widget { public: ~Widget() {} //假设这个析构函数可能会抛出异常 }; int main() { std::vector<Widget> v; return 0; }
当main()函数执行结束会调用类Widget的析构函数,那如果这个vector里面有10个对象,需要调用析构函数10次,如果第一个对象调用析构函数的时候有的异常没处理,程序之后可能会有很多问题。所以别让异常逃离析构函数,应该在析构函数有对异常的处理操作
- 按照书上的例子:有如下的伪代码。
class DBConnection { public: static DBConnection create(); private: void close(); }; class DBConn { public: ~DBConn() { db.close(); } private: DBConnection db; }; int main() { DBConn dbc(DBConnection::create()); return 0; }
- 通过DBConn来创建一个DataBase的连接,用户不用记得去调用close()操作,这样会让代码更OK。
- 但这样并不完美,如果close的调用有问题,没有做任何的操作,那么会为程序带来不确定性,这是不希望的。
-
通过try catch析构函数的异常,让程序更加安全
DBConn::~DBConn() { try { db.close(); } catch (...) { //此处可加上异常的log std::abort(); } }
更好的办法:让使用者有机会处理close()带来的异常,从而可以规避程序异常带来的问题。
class DBConn { public: DBConn::~DBConn() { if (!closed) { try { db.close(); } catch () { //此处可加上异常的log std::abort();// 是abort还是做什么操作可根据实际情况来 } } } void close() { db.close(); closed = true; } private: DBConnection db; bool closed; };
-
总结:需要在析构函数考虑程序异常带来的问题,并做一些防护操作。