博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
第七篇:别让异常逃离析构函数
阅读量:6426 次
发布时间:2019-06-23

本文共 1995 字,大约阅读时间需要 6 分钟。

前言

       析构函数的作用在于完成对象销毁的一些“善后工作”,然而,某些不科学的设计会产生一些问题。

       本文将说明其中的一种不科学设计 - "将异常处理机制设定在析构函数中" 会产生的问题,以及解决方案。

问题描述

       首先,请看一下一段代码:

1 class Widget { 2 public: 3     //...... 4     ~Widget() {    // 假定这个析构函数可能会吐出异常 5         //...... 6     } 7     //...... 8 }; 9 10 void doSomething()11 {12     //......13     std::vector
v;14 //......15 }

       当 doSomething 函数执行完毕的时候,会开始析构容器 v 中存放的各个 Widget 对象。

       然而,该对象析构函数可能会吐出异常。在这种情况下,将会吐出容器中对象个数的异常,这就会导致程序运行的不确定性。

实例分析

       如果在对象结束的时候,必须执行一个可能抛出异常的动作,那该怎么办呢?

       下面通过一个实际应用中的例子,来说明如何解决这个问题。

       首先,定义两个类分别负责数据库连接以及该类资源的管理:

1 // 该类负责数据库的连接 2 class DBConnection { 3 public: 4     //...... 5     static DBConnection create();    // 建立一个DBConnection对象 6     //...... 7     void close(); 8     //...... 9 };10 11 // 该类负责类DBConnection的资源管理12 class DBConn {13 public:14     //......15     ~DBConn() {    // 析构函数确保数据库连接总是会被关闭16         db.close();17     }18     //......19 private:20     //......21     DBConnection db;22     //......23 };

       这样,客户可以写出如下代码以管理数据库连接:

1 {2     //......3     DBConn dbc(DBConnection::create());4     //......5 }

       该段代码结束时,DBConn 对象可能会抛出异常,而一旦异常抛出,就有可能产生问题描述中所说的那种问题现象。

       正确的做法是:将 close() 的执行移交给用户,然后再在析构函数中try and catch,请看解决方案代码:

1 // 修改后的DBConn类实现 2 class DBConn { 3 public: 4     //...... 5     void close() {    // 要求用户自己关闭数据库对象 6         db.close(); 7         closed = true; 8     } 9     //......10     ~DBConn() {11         if (!closed) {    // 如果用户忘记了这么做,就采用 try catch 机制吞下异常。12             try {13                 db.close();14             }15             catch (...) {16                 // 记录此次 close 失败17                 //......18             }19         }20     }21     //......22 private:23     //......24     DBConnection db;25     bool closed;    // 增设此变量用以判断用户是否已经自行调用 close(),用户也可根据此变量判断 close() 是否顺利执行并作出相应的异常处理。26     //......27 };

       这种做法实质是种“双保险”:首先要求用户自行调用 close()。如果用户忘了,也会有 try catch吞掉异常。

       最好的情况是用户按照类使用手册的要求自行调用 close()。用户要是实在粗心大意,忘记了,那就只能让 catch 去吞掉异常,在这种情况下,客户没有资格抱怨,说直接吞掉异常不好。

小结

       要多多结合实际应用,合理使用 C++ 提供的 try 和 catch 机制,写出健康而美妙的代码。

转载地址:http://siyga.baihongyu.com/

你可能感兴趣的文章
在MyEclipse下使用JUnit
查看>>
Hashtable的使用
查看>>
n&(n-1)的妙用
查看>>
嵌入式ARM系统实战开发视频教程
查看>>
iOS开发篇--OC 过程式编程讲解
查看>>
java学习笔记4
查看>>
ELK之logstash系统日志和nginx,tomcat日志收集-4
查看>>
Maven学习总结(十)——使用Maven编译项目gbk的不可映射问题
查看>>
阶梯流程图在PowerPoint2013中如何制作?工作总结ppt模板
查看>>
Java基础学习总结(9)——this关键字
查看>>
Maven学习总结(四)——Maven核心概念
查看>>
Java基础学习总结(23)——GUI编程
查看>>
C/C++的类型转换
查看>>
Maven学习总结(七)——eclipse中使用Maven创建Web项目
查看>>
如何创建泛型数组
查看>>
创建Winodws 2008 R2 SP1 群集
查看>>
MYSQL的几种备份方法
查看>>
redhat 7 手册
查看>>
kvm使用网卡桥接
查看>>
关于javascript
查看>>