如何写出健壮的C++代码?

这个问题是没有完整的答案的,我们永远在路上。

还有一种说法是,要写出健壮的C++代码,你要先能写出健壮的代码。

扯远了,回到话题。

昨天写了个类,功能是从字符串中读取算术表达式,计算后返回结果。实际上就是Python的eval()函数,不过C++和AS3都没有这个功能,所以要自己写一个。实现也比较简单,首先是要解析字符串生成逆序波兰式,然后再递归运算逆序波兰式得到结果。每个波兰式节点有以下定义:

enum RPN_ENTRY_TYPE
{
    OPERATOR_TYPE = 0,
    OPERAND_TYPE,
}

struct RPN_ENTRY
{
    RPN_ENTRY_TYPE eType;
    union
    {
        char chOperator;
        int nOperand;
    }
}

每个节点有可能保存着操作符(operator)或者操作数(operand),有一个枚举用以标识当前节点是什么类型,随后跟着一个存放着操作符或操作数的联合体。

由于是结构体,这货使用起来比较麻烦,要人手逐个为其每个字段赋值:

RPN_ENTRY cEntry;
cEntry.eType = OPERATOR_TYPE;
cEntry.chOperator = '+';
stack.push_back(cEntry);

我的代码中有多处需要这样使用,先新建RPN_ENTRY对象,然后入栈。处于偷懒的目的,我为RPN_ENTRY添加了两个构造函数。这样,入栈和对象的创建就可以在一步完成:

struct RPN_ENTRY
{
    // structure defines
    // ...

    RPN_ENTRY(char chOperator)
    {
        this.eType = OPERATOR_TYPE
        this.chOperator = chOperator
    }

    RPN_ENTRY(int nOperand)
    {
        this.eType = OPERAND_TYPE
        this.nOperand = nOperand
    }
}

//...

stack.push(RPN_ENTRY('+')) // operator
stack.push(RPN_ENTRY(123)) // operand

我觉得我的生活瞬间美满起来了。接下来就是代码入库前要做的同行评审,让老大过代码。老大看到这一段时沉吟许久,说:

“有没有考虑过以后别人接手你的这段代码?那个人也许会先int op = ‘+’,然后stack.push(RPN_ENTRY(op))”。

显然我是没有考虑过这点。C++是一门弱类型语言,因此“int op = ‘+’”这样的操作是合法的。如果真有人这么做了,那么结果肯定会是出错。我的这段代码是不够健壮的。

正确的做法是另写两个名字不同的内联函数来完成这件事:

inline RPN_ENTRY OperatorEntry(char chOperator)
{
    RPN_ENTRY cEntry;
    cEntry.eType = OPERATOR_TYPE;
    cEntry.chOperator = chOperator;
    return cEntry;
}

inline RPN_ENTRY OperandEntry(int nOperand)
{
    RPN_ENTRY cEntry;
    cEntry.eType = OPERATOR_TYPE;
    cEntry.nOperand = nOperand;
    return cEntry;
}

这样便可以大大减少使用者误操作的可能性,毕竟函数的用途在函数名中已经得到了很好的体现。


最近一直处于Python、C++和AS3混编的状态,不得不说经过比较,写C++最费神费力。比如这个eval类,实际上我是先使用AS3写成的,这花了我很少的时间。随后,我以近乎照抄的方式将这个类从AS3中移植到C++里,这竟花了我将近3倍的时间!可以预见,如果我一开始是以C++直接写这个类,大概要花费近4-5倍的时间。

实际上如果只需要实现功能,那移植到C++并不需要花太多的时间。然而AS3代码运行于客户端,C++运行于服务端,服务端的代码要求“简洁,高效,不宕机”。高效意味着尽量少的使用stl库,简洁意味着在没有stl库的情况下你要写得比较简洁,不宕机就意味着你要考虑到每种可能会导致宕机的状况。因此,非常耗费脑细胞。

我的老大亦是我师傅,对代码要求非常严,在过代码的时候也很认真(真的就是一行一行的看)。在这种老大的手下会比较辛苦,不过提高也能更快。

如何写出健壮的C++代码?》上有5条评论

  1. 博主说的很有道理 之前老大也是这样 每段代码都会仔细看 自己却没有仔细看自己的代码,肯定是有逻辑没有彻底处理完的情况 后来就总结了经验 反复考虑才动手写代码。

发表评论

电子邮件地址不会被公开。 必填项已用*标注