首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > C++ >

哪些情况下推荐用错误?哪些情况下必须用错误

2012-04-12 
哪些情况下推荐用异常?哪些情况下必须用异常?关于异常(Exception):看了一整天的异常,throw异常、先try再cat

哪些情况下推荐用异常?哪些情况下必须用异常?
关于异常(Exception):
看了一整天的异常,throw异常、先try再cath异常……,自我感觉好像基本掌握异常怎么使用了,但还是想不通为什么要使用异常,什么情况下需要用异常?可能回答:程序中可能出现问题也可能正常运行的地方使用异常。这样的地方真的需要用异常来处理吗?看一个最简单的异常例子:
bool   dosomething()   throw(MyException);//函数声明
//函数定义略
void   funA()
{
try
{
dosomething();
}
catch(MyException&   e)
{
cout   < <   “error”   < <   endl;
}
}
而与之相对应的不使用异常机制的代码如下:
bool   dosomething();//函数声明
//函数定义略
void   funA()
{
if(!dosomething())   cout   < <   “error”   < <endl;
}
而且使用异常时还需要或自定义或从CException派生MyException(当然据说多数情况下直接使用已有的CException派生类就足够了)。
最不能容忍的是当一个异常抛出之后,如果一直没有catch模块处理,他最终是会导致abort()的。
或许你会讲Exception中包含了许多关于错误的信息,可以是字符串(如e.what()),可以是数值等,而dosomething只能返回true或false,真是这样的吗?将dosomething()改为“int   dosomething();”亦或是更毒的“int   dosomething(LPTSTR   lperrstr   =   null)”如何?
令我感觉确有必要使用异常的一个例子(例子代码来源于网络,出处不可考)(多处申请资源却在一个地方集中释放,使代码的脉络更清晰):
bool   bar1();
bool   bar2();  
bool   bar3();  
bool   foo()  
{  
        char   *   p1   =   new   char[10];  
        if(!bar1()){  
                delete   p1;  
                return   false;  
        }  
        char   *   p2   =   new   char[10];  
        if(!bar2()){  
                delete   p1;                           //   要释放前面申请的所有资源  
                delete   p2;  
                return   false;  
        }  
        char   *   p3   =   new   char[10];  
        if(!bar2()){  
                delete   p1;                           //   要释放前面申请的所有资源  
                delete   p2;  
                delete   p3;  
                return   false;  
        }  
}  
这种流程显然不如:  
void   bar1()   throw(int);  
void   bar2()   throw(int);  
void   bar3()   throw(int);  
void   foo()   throw   (int)  
{  
        char   *   p1   =   NULL;  
        char   *   p2   =   NULL;  
        char   *   p3   =   NULL;  
        try{  
                char   *   p1   =   new   char[10];  
                bar1();  
                char   *   p2   =   new   char[10];  
                bar2();  


                char   *   p3   =   new   char[10];  
                bar3();  
        }  
        catch(int){  
                delete   p1;                 //   集中释放资源  
                delete   p2;  
                delete   p3;  
                throw;  
        }  
}
上面的例子可以认为是推荐使用异常,那么还有哪些情况下推荐用异常呢?有没有哪些情况下必须用异常?请使用简短代码实例作答。
PS:鄙视形如“顶”、“标记”、“收藏”、“好帖”、“自已上网搜搜”及超过50行的答案。

[解决办法]
to lijianbest:
若是想学习就端正好态度。更多的东西是自己去实践去领会,看了一天异常就发个贴子能成什么气候。

to cunsh:
不要写异常规范这一点Herb Sutter在他的基本书中反复强调过,比如《Exceptional C++ Style》第13条 "A Pragmatic Look at Exception Specifications "。

可以参考 http://www.gotw.ca/publications/mill22.htm

其中总结出来的经验是:

Moral #1: Never write an exception specification.

Moral #2: Except possibly an empty one, but if I were you I’d avoid even that.

[解决办法]

看看这边文章

异常是为了让程序员更加关注正常的程序执行序列而设计的. 在异常处理出现后, 程序编制方便了很多.



编程序有80/20原则, 甚至是90/10原则, 即80%的精力花费在20%的事情上, 这20%的事情就是各种出错的处理. 如果编制一个7x24小时运行的程序, 没有异常处理机制的话, 程序中将充斥着if语句, 类似下面:

if ((fr = fopen( "1.txt ", "rt ") == null)

....

if ((fread(...)) > 0)

....

if ((len = fwrite(...)) > 0)

....

几乎所有的库函数调用都需要加上正确性判断, 这样的程序编制非常累.

有了异常处理机制之后, 我们可以这样写:

try

{

fr = fopen( ".... ", "rt);

len = fread(....);

len = fwrite(....);

}catch(FileException e)

{//处理异常情况

}

由于C++中有异常处理机制, 所以上面的例子用C来写.



再说一下异常与普通错误的区别, 本人使用一个原则, 即:错误是否是你可以控制的, 用这个原则来划分异常与错误. 如: 从数据库中读数据, 如果数据库坏掉, 或者连接断掉, 你束手无策, 这种情况下, 就使用异常; 如果应该从数据库中读出100条记录, 但数据库中只有10条, 就使用错误返回方式.



异常处理机制是编程的重大改进. 但使用也比较复杂. 在对异常编程时需要注意的很多, 如:不要截获你不能处理的异常(自然有人管), 异常处理与finally(OO Pascal/Java中的)的关系(需要真正理解), 异常的展开机制, 语言级别的异常与操作系统级别的异常(SHE)的区别, 还有上面说到的异常与错误的设计区分等.





大致的概念是:误是否是你可以控制的, 用这个原则来划分返回值和异常



能控制,就返回值,不能,就异常。



可是,这个错误终究也是由你调用的函数发生的,而不论什么错误,其实都是可以控制的,比如

如果读写文件的时候,硬盘扯了,那总会有一个中断发生,这时某个够底层的函数就可以处理这个错误,然后返回一个 -1 -2什么的告诉调用者,-1 代表物理硬盘损坏什么的。



所以只要函数是人编写的,那就应该可以处理这个错误。

另一种概念是: 可以使处理错误的代码远离错误。



.........


全文


http://wvins.spaces.live.com/blog/cns!EE5784A9623608E5!162.entry
[解决办法]
其实lz基本上已经了解异常了,只是lz自己还没有意识到这一点,下面分析一下

最不能容忍的是当一个异常抛出之后,如果一直没有catch模块处理,他最终是会导致abort()的。
-----------------------
如果你的错误是严重的,并且你使用返回值的方式,那么调用者(一个粗心的家伙)可能忽略这个错误,这可能导致一些未定义的行为或者崩溃。如果你使用异常,调用者忽略的话也会导致崩溃,但这个时候崩溃的原因是已知的,调用者可以很容易的定位这个错误。


或许你会讲Exception中包含了许多关于错误的信息,可以是字符串(如e.what()),可以是数值等,而dosomething只能返回true或false,真是这样的吗?将dosomething()改为“int dosomething();”亦或是更毒的“int dosomething(LPTSTR lperrstr = null)”如何?


-------------------------
你当然可以使用“int dosomething(LPTSTR lperrstr = null)”,但是如果每次写代码你都要构建这样一个框架,会不会太累?于是你会去寻找一个一劳永逸的办法,其实异常的提出者和你想法差不多(可能想得还多点),所以,异常就诞生了。因此,异常也就是提供了一种错误处理的方法,其背后并没有什么深不可测的思想。


令我感觉确有必要使用异常的一个例子
...
上面的例子可以认为是推荐使用异常,那么还有哪些情况下推荐用异常呢?有没有哪些情况下必须用异常?
---------------------------------------------------
lz的例子很好的体现了异常(或者说这种思想)的强大之处。即使不需要释放资源,异常也比你在每个函数调用前加上一个判断要好得多。对于推荐使用异常的情况,这可能需要具体的分析。就我而言,如果是设计一个IO框架,我一定会使用异常。IO可能的错误太多,我不会让用户仅仅为了读一个文件,而在逻辑中嵌入一大堆错误处理函数(实际上用户往往忽略这些错误,这样后果可能更严重),利用异常分离一般的逻辑和错误逻辑会更好。有没有哪些情况必须使用异常,当然,如果你调用了一个使用异常的函数,你就必须使用异常,不然你怎么捕获他的错误。。。


最后,再多说点。异常一定是抛出给调用者的,你抛出异常意味你不能处理这个错误,所以你把它交给调用者处理(我见过一些人在函数内部抛出异常,然后在函数内部捕获,这没什么技术问题,但是从设计上来讲确实没有必要)。另外,iambic()提到不要写异常规范,这仅仅是一个c++的原则,因为c++对于异常规范的实现是模糊的,对于模糊的实现,最好的办法就是别去用它。
[解决办法]
C++异常是C++语言提供给程序员的一种全新的程序设计方法,它可以使程序的逻辑部分与错误处理部分分离,从而极大地提高程序的可读性。当然,异常肯定会带来性能上的损失。
所以,用不用异常,完全是看程序员自己的想法----你到底是在意性能还是在意可读性。
“把哪些情况当作异常来处理是库设计中很难的一部分”---- < <C++ Primer> > 如是说。
我对异常的使用有如下的看法:
1.如果程序模块是自己写的,并且是供自己使用的,那么没必要用异常。
2.如果你的模块是供别人使用的,可以用异常。毕竟你能发现错误,却不知道如何去处理这个错误,用异常通知调用者,无可厚非。
3.如果你用别人的模块,那就得遵守他的规矩,他用异常你就用,他不用你也不用。
4.其实用异常会逐渐的成为一种潮流,就像C++的类一样,最终会流行的。现在MFC的程序就是在顶层框架外加了一个try catch的。
5.大型程序无法避免使用异常。程序规模越庞大,越可能发生不可预知的错误。通过异常,至少可以让你的程序能够体面的退出。比如QQ崩溃之后,会弹出一个对话框“发生未知错误,QQ需要重新启动”,大概是这样写的吧。总之这样的对话框比直接弹出一个非法操作的对话框要好看一些。其实弹出非法操作对话框也是windows seh的一部分。

我的观点总结成一句话就是:随着计算机性能的提高,异常这种程序设计方式早晚会流行起来的。

热点排行