Experience 1:
Do not spit out exceptions. If a function called by the Destructor may throw an exception, the Destructor should capture any exceptions and swallow them (not spread) or terminate the program.
Example:
Class DBConnection {public: static DBConnection create (); // return the DBConnection object void close () ;}; class DBConn {// This class is used to manage the DBConnection object public :~ DBConn () {// make sure that the database connection is always closed. try {db. close ();} catch (Exception e) {// create a running record and write down the call to close failed // 1. call the abort end program to prevent exceptions from spreading from the destructor. // This will lead to ambiguous behavior std: abort (); // 2. alternatively, you can choose not to call the std: abort () function and directly swallow the exception} private: DBConnection db ;};
Experience 2:
If the customer needs to respond to exceptions thrown during the running of an operation function, the class should provide a common function (not in the destructor) to execute this operation.
Example:
Class DBConnection {public: static DBConnection create (); // return DBConnection object void close () ;}; class DBConn {// This class is used to manage DBConnection object public: void close () // double insurance. Customers can choose how to handle errors by themselves {db. close (); closed = true ;}~ DBConn () {// make sure that the database connection is always closed. try {db. close ();} catch (Exception e) {// create a running record and write down the call to close failed // 1. call the abort end program to prevent exceptions from spreading from the destructor. // This will lead to ambiguous behavior std: abort (); // 2. alternatively, you can choose not to call the std: abort () function and directly swallow the exception} private: DBConnection db; bool closed ;};