首页新闻找找看学习计划

函数返回值处理策略

0
[已解决问题] 解决于 2017-10-11 17:55

      在使用C编程的时候,为了保证程序的稳壮性,通常需要对函数调用的返回值做充分的处理。但是这样会带来一些别的副作用,例如代码的可阅读性很差,很大一部分代码用来处理错误。参考驱动代码里面,采用了较多了goto语句,不过还是有蛮多的返回值判断。曾经看到过一份为某个模块代码,里面处理的方式比较巧妙:

int foo(void)
{
    int ret = 0;

    ret |= xxx_module_do_a(ret, x, y);
    ret |= xxx_module_do_b(ret, xxx, ddd);
    ret |= xxx_module_do_c(ret, k, i, l);
    ret |= xxx_module_do_d(ret, o, p, q);

    if ( ret != 0)
    {
        //处理具体的错误
    }

    return x;
}

//模块函数里面这样处理ret
int xxx_module_do_a(int ret, x, y)
{
    if ( ret != 0 )
    {
        return ret;
    }

    ret |= do_something();

    return ret;
}

      通过位域来标识不同的错误码,将上一个模块函数调用返回的错误码传入下一个函数调用,如果发现有错误,立即返回。到最后面集中处理错误码,这样虽然带来了一定的函数调用开销,但是可阅读性大大提高了。其实这个处理方式相当于goto语句的处理方式,只是把返回值判断的那句分散到了每个模块函数里面,并且goto不会带来调用开销。

    请问各位,你们都有什么样的处理方法,分享一下。

thammer的主页 thammer | 初学一级 | 园豆:148
提问于:2017-09-25 16:11
< >
分享
最佳答案
0

C的话,你的foo函数其实做的差不多了。

但是C++的话,其实可以参考boost.asio的方式,关键函数都有异常版本和返回值版本。

以connect函数为例:

1. boost::asio::connect( basic_socket< Protocol, SocketService > & s, Iterator begin, boost::system::error_code & ec )

2. boost::asio::connect ( basic_socket< Protocol, SocketService > & s, Iterator begin )

如果你不想要异常抛出,你必须申明一个error_code,这个算是一个你需要做异常处理的提醒。老实说,return的话,很容易被忽略。

如果你真要忽略error_code也可以,如果有问题就抛一个异常,这个异常你可以在一个地方集中处理,并且主逻辑可以只写成功的case非常的清晰易读,但是异常要用好的话,也有蛮多的学问,比如对象的生命周期的管理,已经操作的回滚等等。。。

个人的话,会倾向于使用版本1.

奖励园豆:5
asahi86 | 菜鸟二级 |园豆:242 | 2017-09-26 09:29

C++不太熟悉,还是高级语言机制完善些。

thammer | 园豆:148 (初学一级) | 2017-09-26 14:49
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册