C++基础语法:异常处理(一)

前言

      "打牢基础,万事不愁" .C++的基础语法的学习."学以致用,边学边用",编程是实践性很强的技术,在运用中理解,总结.

引入

        在编写程序时,可能会因为程序错误或者编译问题等出现异常,因此设计了异常处理机制来应对.以 6th Edition(以下称"本书")内容做参考.

异常概览

        1.直接终止abort()

        2.函数设计成谓词,不影响程序编写.

        3.异常机制

        4.异常类

        异常的设计思想是:当代码可能出现问题时,标记出来单独处理

        产生异常的语句放在函数中,给可能产生的异常取个名字,方便编写程序.

直接终止

        本书P617,调用std::abort();直接终止程序

        显然这种方式不好.如果程序很大,直接终止后,重新启动还得花时间,对使用者也不友好.

返回错误码

        回顾谓词

        返回值使用bool类型已被定义为谓词---笔者个人定义.分析一点和谓词相关的概念:

        1>任何函数都可以成为谓词.谓词的好处是多一个bool类型的返回结果,指出调用成功或失败

//伪代码
ResultType fun(ParaType pt);            //普通函数,非谓词函数
bool fun(ParaType pt,ResultType* rt);   //谓词

        2>返回结果在下一步程序中用作分支         

//伪代码
if(fun(pt,rt))        //如果调用fun,返回结果为true
    statement;
else                  //如果调用fun,返回false
    statement;

        所以谓词的使用:形式上看有两个地方用了if做分支(谓词和调用谓词)

        本书P617最后一段.一种比异常终止更灵活的方法是,使用函数的返回值来指出问题。 例如,ostream类的get(void)成员通常返回下一个输入字符的ASCII 码,但到达文件尾时,将返回特殊值EOF。对hmean( )来说,这种方法不管用。任何数值都是有效的返回值,因此不存在可用于指出问题的特殊值。在这种情况下,可使用指针参数或引用参数来将值返回给调用程序,并使用函数的返回值来指出成功还是失败。istream族重载>>运算符使用了这种技术的变体。通过告知调用程序是成功了还是失败了,使得程序可以采取除异常终止程序之外的其他措施。程序清单15.8是一个采用这种方式的示例,它将hmean( )的返回值重新定义为bool,让返回值指出成功了还是失败了,另外还给该函数增加了第三个参数,用于提供答案。(黑体字是书上原话)

        输入多值产生异常

        本书P618程序清单15.8,提供了在输入多个值(这里是2个值)产生异常时的解决方案.

        ----回顾输入单个值产生异常的解决,用while,例如需要输入1到6之间的整数.

        参考本书P189程序清单6.14

//使输入值在范围内
int number;
while(!(cin>>number && number>=1 && number<=6)){    //当输入不符合要求时
    cin.clear();                                    //重置输入
    while(cin.get()!='\n');                         //清除多余输入
    cout<<"请输入1到6之间的整数(含1和6)"<

        输入多个值产生异常的场景:当输入多个值,使得程序出错不可继续.

        解决方案:谓词+while.谓词中描述异常条件,在主程序中用while循环输入,谓词返回值true或者false产生程序分支,表示当出现异常或者不出现异常时给出的反馈.代码参考本书P618程序清单15.8C++基础语法:异常处理(一)_第1张图片

        注意:原书代码可以做一个修改(笔者改,转载请注明版权:))

//本书代码:谓词函数
bool hmean(double a, double b, double * ans)
{
    if (a == -b)
    {
//        *ans = DBL_MAX;                    //原书代码
          ans=nullptr;                       //修改
          return false;
    }
    else
    {
        *ans = 2.0 * a * b / (a + b);
        return true;
    }
}

        原因:两个可能异常的参数传给谓词函数hmean,函数作出判断,由返回值提供信息(true或false)返回给调用的函数main.当产生异常时(a==-b),计算的值*ans不会被采用,属于占位值(笔者自定义概念),恰巧类型是指针,让他等于0或者nullptr就可以了.

        本书代码中特意找了个DBL_MAX处理占位值,在本书P619做了说明:另一种在某个地方存储返回条件的方法是使用一个全局变量.可能问题的函数可以在出现问题时将该全局变量设置为特定的值,而调用程序可以检查该变量。传统的C语言数学库使用的就是这种方法,它使用的全局变量名为errno。当然,必须确保其他函数没有将该全局变量用于其他目的。(黑体字是原话),属于另一种思路:使用全局变量做异常判定.

        红色部分想表达的意思如以下代码

//伪代码
if(*ans==DBL_MAX)    //在调用函数中用来表示出现异常
    statement;

        而按笔者思路的写法

//伪代码
if(ans==0)            //在调用函数中表示异常产生
    statement;
//这样写优雅一点
if(!ans)              //在调用函数中表示异常产生
    statement;

==================================内容分割线===============================

以下内容和异常无关

引申内容:全局变量

        本来hmean函数设计出来就是判定是否产生异常的,为什么还要用一个占位值去判定,直接调用hmean不就可以了吗? 我想目的应该是做全局变量用于信息共享.

        从全局变量分析,在C语言那本经典书里,我记得作者说过"一个好的程序可以不用全局变量".全局变量的坏处是可以被修改,以至于出了问题都不知道去哪里找.但如果程序很大,需要有很多人一起编写,没有全局变量,又怎么能互通信息呢?

        可以用私有继承来保证部分人修改权限,部分人只有访问权限. 有修改权限的人,用全局变量来通信.只有读取权限的人,根据读取的全局变量来编写代码.此部分内容后面作专题

        本书的*ans就是一个全局变量,标记异常状态,给他个值DBL_MAX,拿去判断是否产生异常.所以不是笔者的想法比书作者高明,而是作者考虑得更周全,用法更广泛.    

        再想一想,标记状态也可以用枚举啊.这里的异常状态就两个:异常或没有异常.拿枚举来写,也就两个值,没有必要.枚举还是适合于状态值多一些的场景.

==================================内容分割线===============================

小结

        对异常的初步理解,下一篇对异常机制,异常类作分析理解 

你可能感兴趣的:(C++,c++,开发语言)