网络编程 | 站长之家 | 网页制作 | 图形图象 | 操作系统 | 冲浪宝典 | 软件教学 | 网络办公 | 邮件系统 | 网络安全 | 认证考试 | 系统进程
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++语言常见问题解答(3).
.More Effective C++:自增和自减.
.C语言入门之文件(1).
.实例讲解.
.链表的C语言实现之删除结点.
.在c/c++中利用数组名和指针进行排.
.C++Builder中"异形"按.
.在C++Builder中使用DLL.
.C程序设计语言概论.
.五种VC++数据库开发技术的比较.
.C程序设计基础之多维数组的指针变.
.C++基础:初始化类对象.
.Windows中的消息详细列表.
.递归下降纯解释器编写的困惑.
.求阶乘算法(0---10000)标准C++.
.一个简易的proxy程序的开发过程(.
.学习c++的50条忠告(初学者必看).
.使用 C++ Builder&nbs.
.Windows Sockets:套接字通知.

使用C++异常来取代exit()函数

发表日期:2008-3-8



  从C语言开始接触C++的人,恐怕都知道exit()这个函数,似乎现在很多的程序员都有这样一种习惯,在程序一碰到错误、或任务刚完成时,把调用exit()函数当成是一种最好的结束程序的方法。
在以前遗留的许多老式C/C++代码中,这种现象非常普遍,但当手头的软件项目逐步进展并越来越大时,就不得不面临合并以前分散的各个模块这项工作,此时,假如还有人记得起软件日志记录、错误宽容度、或至少适当的清理工作,就已经是万幸了。本文中要说的方法,决不是一条设计准则,但是可减轻修正那些未良好设计及实现的老式代码时所带来的痛苦。

  用return来取代exit,无疑是解决此问题最显而易见的方法,假如软件项目非常简单,这也是最高效的解决方案;然而,项目中经常有成打的函数分布在多个源文件中,且这些函数的调用也嵌套在很深的层次中,那么,事情就变得棘手了。假如在这种情况中,所有的函数都返回void,还是有可能修改它们,让其返回一个退出码(exit code)的,但所付出的代价也很大;假如函数已经能返回一个有意义的值,只是在碰到错误时,调用了exit(),那么这项工作会变得更消耗时间,也会更加轻易出错。这里说点题外话,使用exit()也是有可取之处的,当老式代码没有设计返回任何东西时,假如想得到返回码(return code),只有靠exit()了。

  有关此问题,还是有一个解决方法的,在这种情况下,我们假定所有的源代码已经为C++格式,或无需全部编译就可以移植为C++格式,把所有exit出现的地方全部换成throw(这可以自动完成,甚至无须理解老代码是怎样工作的);接着,在任何适当的地方,捕捉为整数的异常码,这种方法还可依据严重性或恢复程度的不同,在不同层面上处理错误。

  请看以下示例,原始代码如下:

// main.cpp
void main() {
 //初始化
 ...
 ProcessMail(...);
}

//另一个源文件
void ProcessMail(...) {
 //初始化
 ...
 if ( initializationError ) {
  printf("faild to init!!!\n");
  exit(-1);
 }
 while ( !shutdown ) {
  ReadMail(...)
  //继续处理
  ...
 }
}

void ReadMail(...)
{
 ...
 //对ReadBytes()的调用出现在函数内的多处地方,包括在循环中。
 nBytesAvailable = ReadBytes(...)
 ...
}

//另一个源文件
int ReadBytes(...)
{
 //读取数据
 ...
 if ( error ) {
  printf("there was an error!!\n");
  exit(-1);
 }
 return nBytesRead;
}进入讨论组讨论。

  在原始代码中缺少恢复或日志记录的功能,假如发生了一个错误,程序就会"消失"不见了,让用户手足无措。下面是重新组织后的代码,注重,没有修改函数修饰符:

void main() {
 //初始化
 ...
 try {
  ProcessMail(...);
 } catch (int ret) {
  switch (ret) {
   case E_INITIALIZATION_FAILURE: ...
   case E_IRRECOVERABLE: ...
   ...
  }
 }
}

void ProcessMail(...) {
 //初始化
 ...
 if ( initializationError ) {
  throw(E_INITIALIZATION_FAILURE);
 }

 while ( !shutdown ) {
  try {
   ReadMail(...)
  } catch (int ret) {
   switch (ret) {
    case E_READ_ERROR:
     //记录错误信息
     ...
     //试图恢复
     ...
     if ( recovered ) {
      continue;
     } else {
      throw(E_IRRECOVERABLE);
     }
     break;
    case ...
   }
  }
  //继续处理
  ...
 }

 //throw()可以用来取代缺少的返回码
 //但也要注重由此带来的性能损失

 throw(S_OK);
} // ProcessMail()

void ReadMail(...)
{
 ...
 //在此无须捕捉异常
 nBytesAvailable = ReadBytes(...)
 ...
}

int ReadBytes(...)
{
 //读取数据
 if ( error ) {
  throw(E_READ_ERROR);
 }
 return nBytesRead;
}
  现在,修改以前遗留的老式项目时,是不是多点信心了呢?进入讨论组讨论。

上一篇:C++函数如何操作堆栈指针esp 人气:776
下一篇:C++中使用BHO来屏蔽特定网站 人气:630
浏览全部C/C++的内容 Dreamweaver插件下载 网页广告代码 祝你圣诞节快乐 2009年新年快乐