• 函数
    • 函数设计
      • 建议8.1.1 避免函数过长,函数不超过50行(非空非注释)
    • 内联函数
      • 建议8.2.1 内联函数不超过10行(非空非注释)
    • 函数参数
      • 建议8.3.1 函数参数使用引用取代指针
      • 建议8.3.2 使用强类型参数,避免使用void*
      • 建议8.3.3 函数的参数个数不超过5个

    函数

    函数设计

    建议8.1.1 避免函数过长,函数不超过50行(非空非注释)

    函数应该可以一屏显示完 (50行以内),只做一件事情,而且把它做好。

    过长的函数往往意味着函数功能不单一,过于复杂,或过分呈现细节,未进行进一步抽象。

    例外:某些实现算法的函数,由于算法的聚合性与功能的全面性,可能会超过50行。

    即使一个长函数现在工作的非常好, 一旦有人对其修改, 有可能出现新的问题, 甚至导致难以发现的bug。建议将其拆分为更加简短并易于管理的若干函数,以便于他人阅读和修改代码。

    内联函数

    建议8.2.1 内联函数不超过10行(非空非注释)

    说明:内联函数具有一般函数的特性,它与一般函数不同之处只在于函数调用的处理。一般函数进行调用时,要将程序执行权转到被调用函数中,然后再返回到调用它的函数中;而内联函数在调用时,是将调用表达式用内联函数体来替换。

    内联函数只适合于只有 1~10 行的小函数。对一个含有许多语句的大函数,函数调用和返回的开销相对来说微不足道,也没有必要用内联函数实现,一般的编译器会放弃内联方式,而采用普通的方式调用函数。

    如果内联函数包含复杂的控制结构,如循环、分支(switch)、try-catch 等语句,一般编译器将该函数视同普通函数。虚函数、递归函数不能被用来做内联函数

    函数参数

    建议8.3.1 函数参数使用引用取代指针

    说明:引用比指针更安全,因为它一定非空,且一定不会再指向其他目标;引用不需要检查非法的NULL指针。

    选择 const 避免参数被修改,让代码阅读者清晰地知道该参数不被修改,可大大增强代码可读性。

    建议8.3.2 使用强类型参数,避免使用void*

    尽管不同的语言对待强类型和弱类型有自己的观点,但是一般认为c/c++是强类型语言,既然我们使用的语言是强类型的,就应该保持这样的风格。好处是尽量让编译器在编译阶段就检查出类型不匹配的问题。

    使用强类型便于编译器帮我们发现错误,如下代码中注意函数 FooListAddNode 的使用:

    1. struct FooNode {
    2. struct List link;
    3. int foo;
    4. };
    5. struct BarNode {
    6. struct List link;
    7. int bar;
    8. }
    9. void FooListAddNode(void *node) { // Bad: 这里用 void * 类型传递参数
    10. FooNode *foo = (FooNode *)node;
    11. ListAppend(&fooList, &foo->link);
    12. }
    13. void MakeTheList() {
    14. FooNode *foo = nullptr;
    15. BarNode *bar = nullptr;
    16. ...
    17. FooListAddNode(bar); // Wrong: 这里本意是想传递参数 foo,但错传了 bar,却没有报错
    18. }
    • 可以使用模板函数来实现参数类型的变化。
    • 可以使用基类指针来实现多态。

    建议8.3.3 函数的参数个数不超过5个

    函数的参数过多,会使得该函数易于受外部变化的影响,从而影响维护工作。函数的参数过多同时也会增大测试的工作量。

    如果超过可以考虑:

    • 看能否拆分函数
    • 看能否将相关参数合在一起,定义结构体