动态网站制作指南 [  QQ表情  ]
[ 投票调查 ]
[ 企业邮箱 ]
[ 网站空间 ]
网络编程 | 站长之家 | 网页制作 | 图形图象 | 操作系统 | 冲浪宝典 | 软件教学 | 网络办公 | 邮件系统 | 网络安全 | 认证考试 | 系统进程
ASP源码 | .Net源码 | PHP源码 | JSP源码 | JAVA源码 | CGI源码 | VB源码 | C++源码 | Delphi源码 | PB源码 | VF源码 | 汇编 | 服务器
Firefox | IE | Maxthon | 迅雷 | 电驴 | BitComet | FlashGet | QQ | QQ空间 | Vista | 输入法 | Ghost | Word | Excel | wps | Powerpoint
asp | .net | php | jsp | Sql | c# | Ajax | xml | Dreamweaver | FrontPages | Javascript | css | photoshop | fireworks | Flash | Cad | Discuz!
当前位置 > 网站建设学院 > 网络编程 > C/C++教程
Tag:注入,存储过程,分页,安全,优化,xmlhttp,fso,jmail,application,session,防盗链,stream,无组件,组件,md5,乱码,缓存,加密,验证码,算法,cookies,ubb,正则表达式,水印,索引,日志,压缩,base64,url重写,上传,控件,Web.config,JDBC,函数,内存,PDF,迁移,结构,破解,编译,配置,进程,分词,IIS,Apache,Tomcat,phpmyadmin,Gzip,触发器,socket
网络编程:ASP教程,ASP.NET教程,PHP教程,JSP教程,C#教程,数据库,XML教程,Ajax,Java,Perl,Shell,VB教程,Delphi,C/C++教程,软件工程,J2EE/J2ME,移动开发
文章搜索服务
邮件订阅
输入你的邮件地址,
你将不会错过任何关于:
[ C/C++教程 ]的信息

本月文章推荐
.确定一个应用程序是否没有响应.
.Win2K下的Api函数的拦截.
.BCB6与BCB2006控件的安装.
.实现LZARI压缩算法的C++类.
.看我不动也会张的大嘴巴.
.C++基础:函数指针调用方式.
.VC下显示JPEG、GIF图像的简便方法.
.花心.
.C语言入门之联合.
.高质量C++/C编程指南 --&nb.
.跳动的小球.
.gdb基本用法.
.VC的若干实用小技巧(一).
.C++中用于计算四则混合运算表达式.
.使用foreach来读取记录.
.用户界面设计风格说明上.
.算术编码用c++的实现.
.如何提高数据库的访问速度.
.C++中处理XML文件.
.入门教程:C++中的const限定修饰符.

C++箴言:防止异常离开析构函数

发表日期:2008-3-8 |



  C++ 并不禁止从析构函数中引发异常,但是这确实妨碍了实践。至于有什么好的理由,考虑:

  

  class Widget {

   public:

    ...

    ~Widget() { ... } // assume this might emit an exception

  };

  

  void doSomething()

  {

   std::vector v;

   ...

  } // v is automatically destroyed here

  当 vector v 被析构时,它有责任销毁它包含的所有 Widgets。假设 v 中有十个 Widgets,在销毁第一个的时候,抛出一个异常。其他 9个 Widgets 仍然必须被销毁(否则他们持有的任何资源将被泄漏),所以 v 应该调用它们的析构函数。但是假设在这个调用期间,第二个 Widgets 的析构函数又抛出一个异常。现在有两个异常同时在活动中,对于 C++ 来说这太多了。在非常巧合的条件下发生这样两个同时活动的异常,程序的执行会终止或者引发未定义行为。在本例中,将引发未定义行为。与此相同,使用任何标准库容器(比如,list,set),任何 TR1中的容器,甚至是一个数组,都可能会引发未定义问题。并非必须是容器或数组才会陷入麻烦。程序夭折或未定义行为是析构函数引发异常的结果,即使没有使用容器或数组也会如此。C++ 不喜欢引发异常的析构函数。 这比较轻易理解,但是假如你的析构函数需要执行一个可能失败而抛出异常的操作,该怎么办呢?例如,假设你与一个数据库连接类一起工作:

  

  class DBConnection {

   public:

    ...

   

    static DBConnection create(); // function to return

    // DBConnection objects; params

    // omitted for simplicity

  void close(); // close connection; throw an

  }; // exception if closing fails

   更多文章 更多内容请看C/C++技术专题专题,或
  为了确保客户不会忘记调用 DBconnection 对象的 close,一个合理的主意是为 DBConnection 建立一个资源治理类,在它的析构函数中调用 close。这样的资源治理类将在以后的文章中探讨,但在这里,只要认为这样一个类的析构函数看起来像这样就足够了:

  

  class DBConn { // class to manage DBConnection

   public: // objects

    ...

    ~DBConn() // make sure database connections

    { // are always closed

     db.close();

    }

   private:

    DBConnection db;

  };

  它答应客户像这样编程:

  

  {

   // open a block

   DBConn dbc(DBConnection::create()); // create DBConnection object

   // and turn it over to a DBConn

   // object to manage

   ... // use the DBConnection object

   // via the DBConn interface

  } // at end of block, the DBConn

  // object is destroyed, thus

  // automatically calling close on

  // the DBConnection object

  既然能成功地调用 close 那就好了,但是假如这个调用导致了异常,DBConn 的析构函数将散播那个异常,也就是说,它将离开析构函数。这就产生了问题,因为析构函数抛出了一个烫手的山芋。 更多文章 更多内容请看C/C++技术专题专题,或
  有两个主要的方法避免这个麻烦。DBConn 的析构函数能:

  终止程序 假如 close 抛出异常,调用 abort。

  

  DBConn::~DBConn()

  {

   try { db.close(); }

   catch (...) {


    make log entry that the call to close failed;

    std::abort();

   }

  }

  假如程序在析构过程遭碰到错误后不能继续运行,这就是一个合理的选择。它有一个好处是:假如答应从析构函数散播异常可能会引起未定义行为,这样就能防止它发生。也就是说,调用 abort 就预先防止了未定义行为。

  抑制这个异常 起因于调用 close:

  

  DBConn::~DBConn()

  {

   try { db.close(); }

   catch (...) {

    make log entry that the call to close failed;

   }

  }

  通常,抑制异常是一个不好的主意,因为它会隐瞒重要的信息——某些事情失败了!可是,有些时候,抑制异常比冒程序夭折或未定义行为的风险更可取。程序必须能够在遭碰到错误并忽略之后还能继续可靠地执行,这才能成为一个可行的选择。

  这些方法都不太吸引人。它们的问题在于程序无法在第一现场对引起 close 抛出异常的条件做出回应。

  一个更好的策略是设计 DBConn 的接口,以使它的客户有机会对可能会发生的问题做出回应。例如,DBConn 能够自己提供一个 close 函数,从而给客户一个机会去处理从那个操作中发出的异常。它还能保持对它的 DBConnection 是否已被关闭的跟踪,假如没有关闭就在析构函数中自己关闭它。这样可以防止连接被泄漏。假如在 DBConnection 的析构函数中调用 close 失败,无论如何,我们还可以再返回到终止或者抑制。

  

  class DBConn {

  public:

  ...

  

  void close() // new function for

  {

   // client use

   db.close();

   closed = true;

  }

  

  ~DBConn()

  {

   if (!closed) {

    try { // close the connection

     db.close(); // if the client didn’t

    }

    catch (...) { // if closing fails,

     make log entry that call to close failed; // note that and

     ... // terminate or swallow

    }

   }

  

   private:

    DBConnection db;

    bool closed;

  };

  将调用 close 的责任从 DBConn 的析构函数转移到 DBConn 的客户(同时在 DBConn 的析构函数中包含一个“候补”调用)可能会作为一种肆无忌惮地推卸责任的做法而刺激你。你甚至可以把它看作一个忠告(使接口易于正确使用)的违反。实际上,这都不正确。假如一个操作可能失败而抛出一个异常,而且可能是一个需要处理的异常,这个异常就必须来自非析构函数。这是因为析构函数引发异常是危险的,永远都要冒着程序夭折或未定义行为的风险。在此例中,让客户调用 close 并不是强加给他们的负担,而是给他们一个时机去应付错误,否则他们将没有机会做出回应。假如他们找不到可用到机会(或许因为他们相信不会有错误真的发生),他们可能忽略它,依靠 DBConn 的析构函数为他们调用 close。假如一个错误恰恰发生在那时——假如由 close 抛出——假如 DBConn 抑制了那个异常或者终止了程序,他们将无处诉苦。究竟,他们无处着手处理问题,他们将不再使用它。

  Things to Remember

  ·析构函数应该永不引发异常。假如析构函数调用了可能抛出异常的函数,析构函数应该捕捉任何异常,然后抑制它们或者终止程序。

  ·假如类客户需要能对一个操作抛出的异常做出回应,则那个类应该提供一个常规的(非析构函数)函数来完成这个操作。 更多文章 更多内容请看C/C++技术专题专题,或
上一篇:利用C++实现哈夫曼算法 人气:711
下一篇:5.  运算符 人气:436
浏览全部C/C++的内容 Dreamweaver插件下载 常用网页广告代码全集
  最新网站源码 最新软件下载
2008-10-12 team论坛 v2.0.4 bulid 080916 A
2008-10-12 Roclog v3.1.6
2008-10-12 SupeV v1.0.1 简体中文 GBK
2008-10-12 NetCMS v1.6.0.1010 正式版
2008-10-12 PHP考试系统PPFrame v1.2.7
2008-10-12 LPAS个人相册 v1.6.3
2008-10-12 快问仿百度知道系统 动态-静态-互
2008-10-12 方卡广告防点击系统 V1.0 GB2312
2008-10-12 泡菜内容管理系统[PCMS] v1.0 Bu
2008-10-11 联系人分组工具 v1.1 中文破解版
2008-10-11 FaceMelter变脸 v2.0 汉化破解版
2008-10-11 PathTracker道路跟踪仪 v1.2 破解
2008-10-11 Rooms手机聊天室 v0.6.7 破解版
2008-10-11 RemoteDesktop远程桌面 v1.0 破解
2008-10-11 ProRemote远程调音台 v1.0.1 破解
2008-10-11 PicShare照片共享 v1.0.0 破解版
2008-10-11 Photogene照片编辑器 v1.5 汉化破
2008-10-11 WriteRoom共享文档 v1.0 破解版
  发表评论
姓 名: 验证码:
内 容:
站长工具:网站收录查询 | Google PR查询 | ALEXA排名查询 | CSS在线编辑器 | 广告代码 | js/vbs加密 | md5加密 | 进制转换 | UTF-8 转换工具 | Html转换js | Html转换asp | Html转换php | Html转换perl
实用工具:汉字翻译拼音 | 拼音字典 | 符号对照表 | 个税计算 | 实时汇率查询换算 | 经典小工具 | 汉字简繁转换 | 普通单位换算 | 公制单位换算 | 生辰老黄历 | 国内电话区号 | 国家代码与域名缩写 | 文字加密解密 | 健康查询 | 万年历 | 汉字横竖排版 | 手机号码查询 | 计算器 | ip搜索
业务联系 | 广告刊登 | 频道合作 | 投稿荐稿 | 联系方式 | 加入收藏 | RSS订阅
Copyright © 2000-2008 www.knowsky.com All rights reserved | 网络实名:动态网站制作指南 | 沪ICP备05001343号
ホームページ制作 不動産検索システム 求人情報
防水工事·改修工事 フットサル大会 探偵
SEO対策 中国語教室 ホームページ作成