前言:在大学学习了一年时间的编程,发现自己对一些东西理解得不是很深入,写这篇博文主要是发表一下自己对异常机制使用的思考,希望看到这篇文章的人如果有相同疑问的或者对我有什么建议的请回复交流一下。
正文之前先看一下这个例子:
要求编写一个operation函数用于解析字符串类型的中缀表达式并计算出得数,表达式以标准输入流由控制台输入;
这是一个很普遍的例子,相信大家在学习栈的时候都做过这种由中缀表达式变后缀表达式计算得数的编程题但下面问题出来了
问题:在做除法运算时除数不能为零,为零时发生错误,那么错误在哪里处理。
这就是下面要讨论的,我所思考的问题。
这里我对这个问题的回答(就是正文啦 o(≧v≦)o ):
回答一:在operation函数内返回一个异常,在main函数内捕获异常后要求重新输入
思考a:貌似是普遍做法,但在一个要求用户进行输入的函数内处理一个信息除数不能为零的异常,真的大丈夫吗?,如果期间在调用多几个函数会返回各种各样的异常类不会导致main函数里面的异常处理很凌乱吗?
思考b:既然异常种类多起来会变得混乱的话,那么把异常统一成一个输入异常类好像就能解决问题,但是我在另一个函数(已有一个字符串不要求用户输入)调用operation函数时,他会给我抛出一个输入异常啊!这不坑爹了吗!你让我怎么在一个普通不需要输入的函数中处理一个输入异常啊!这不合逻辑,不科学吧!
ok!回答一解决不了,我们换一种回答。
回答二:通过在operation函数返回一个错误值,在main函数中检测后要求重新输入
思考a:这不用思考了吧,我还要返回结果值啊!
思考b:结果值通过传指针或者传引用返回,返回值用于返回错误码。这是底层API的做法但这样做就不能返回具体的错误信息,而且同一个函数中要返回的错误码种类一多起来的时候上一层函数就必须判断返回的是哪一个错误码,导致整个错误处理代码更加臃肿。
回答三:在operation函数中直接处理异常
思考a:operation函数没有要求用户重新输入的职能,如果我们要在operation函数要求重新并获取输入的话,operation函数就获得了一个与本质功能不相关的职能,这是不符合设计模式中的单一职责原则的,且该函数的参数不一定是有用户输入的,根据异常处理的原则一个函数也不应该处理一个不确定要怎么处理的异常。
回答四:在main函数和operation函数之间再加一个代理函数,在operation函数内返回一个除数不能为零异常被代理函数捕获,代理函数再抛出一个输入异常,在main函数内捕获输入异常后要求重新输入
思考a:解决了回答一思考a、b的问题,但像operation函数一多起来就需要大量的代理函数,这也是个问题。
基本上这就我对开头提到的问题的思考,实际上就是对怎样去使用异常处理机制的思考。
总结一下发现上面的问题都基本上是以下矛盾导致,
1、异常类是被上层(至少是上一层)函数调用的,那么异常类的定义应该适应上层函数的需求,但异常类的内涵是由抛出异常的函数决定的,那么异常类定义也应该服从其内涵。
2、异常类是被上层(至少是上一层)函数调用的,那么异常类的定义应该适应上层函数的需求,但可以有多个不同的上层函数调用抛出异常的函数,那么异常类必须适应多个上层函数的需求。
最后,感谢大家来看我写下的拙笔,小弟学习不足,有错误的地方请各位多多回复指正,小弟会感激不已的,也请各位有更精辟见解的大神可以指点小弟一二。
在这里再补充一个自己对自定义异常机制的想法:
定义一组异常类(可继承扩展并自动管理内存带有错误信息),要求所有函数的返回值必须是异常类基类指针(内存动态分配),上层函数必须对所有调用函数的返回值(真正要返回的值通过传引用返回)进行判断(运行时类型识别,派生新类时需要注册到异常管理类)并实现相应的处理函数(类似MFC消息传递机制)。