|
C++自学精简教程 目录(必读)
程序必须要能面对错误情况给出反应,或者说程序员必须要处理错误。
一、错误的类型
1、系统错误
考虑你写了一求数两个整数最大公约数的函数int gcd(int a, int b);
其中a和b都不可以为0
处理方法
函数一开始就判断a,b两个是否有0出现
你的代码开始的地方变成了下面的样子
int gcd(int a, int b)
{
//(1)使用断言
assert(a!= 0 && b!=0);
// 这里开始干正事
}
上面代码使用断言的效果:debug开发模式这里会导致程序死掉。
不过断言只有debug模式才有(release模式会被编译器擦除,写了也等于没写)。
代码的参数者 | 约定 | 原则 | gcd代码的作者 | assert | 保证返回值,方便调用;
底层保证效率 | gcd代码的用户 | 调试环境使用发现错误 | 自己保证别传错误参数 | 2、逻辑错误
考虑你实现了一个json库,用户给你一个字符串,你的json对象就可以根据这个json字符串创建对象,并访问其中的数据:
CJsonObject json;
json.CreateFromStr("{\"name\":\"zhangsan\", \"age\":26\"}");//bad json str
上面的json对象需要一个合法的json字符串才能创建,但是传入的字符在整数26右侧多了一个分号。
这是一个非法的字符串,这时候你作为库作者不知道应该怎么处理。你唯一能做的就是把错误暴露出来。
二、两种处理逻辑错误的方式
1、返回错误码
函数返回错误码,调用函数的人检查错误码。
代码变成下面这样:
CJsonObject json;
int good_json = json.CreateFromStr("{\"name\":\"zhangsan\", \"age\":26\"}");//bad json str
if(good_json != OK)
{
//write log or print some worning to the caller
return ERROR_JSON;//so many error code
}代码参与者 | 约定 | 原则 | CreateFromStr的作者 | 负责抛出错误,而不处理错误 | 库作者不知道该如何处理错误 | CreateFromStr的用户 | 负责发现错误,进而处理错误 | 上层代码保证有效性 | 返回错误码之前,对于有日志的程序,往往还会记录一条日志信息。
日志可以是打印到日志文件,也可以是打印到控制台。方便出现问题的时候,程序员可以据此来发现问题的根源。
2、抛出异常
抛出异常之后,库作者需要捕获异常才知道有没有发生错误。代码变成下面这样:
CJsonObject json;
try
{
json.CreateFromStr("{\"name\":\"zhangsan\", \"age\":26\"}");//bad json str
}
catch(exception e)
{
//错误处理, write log or print some worning to the caller
}
代码参与者 | 约定 | 原则 | CreateFromStr的作者 | 负责抛出错误,而不处理错误 | 库作者不知道该如何处理错误 | CreateFromStr的用户 | 负责发现错误,进而处理错误 | 上层代码保证有效性 | 三、两种处理错误的方式的对比
类型 | 返回错误码 | 抛异常 | 常用场景 | 操作系统 | json库等中间库 | 优点 | 流程完全可控,对于流程比较复杂的场景可以准确定位每一步,并做出处理 | 代码直观,不用每次都判断 | 缺点 | 导出都是判断错误的代码,代码增长比较严重 | 流程复杂的时候,没有合适的地方捕获,提前捕获用户看不到;适合层级比较少的场景 |
|
|