[关闭]
@gnat-xj 2015-11-17T02:31:35.000000Z 字数 6459 阅读 2085

CVRS C++ Coding Style 规范(已经备份)

docs coding_style

read official version: http://cvrs.whu.edu.cn/docs/CVRS-CodingStyleGuide.html

read newest version:


零、绪论

  1. 注释分为两种,第一种是给自己看或者其他看代码的人看,用 // comment 或者 /* comment */
    第二种是会被放到文档中,用 //! comment 或者 /*! comment */(也就是多加一个 ! 的事)。
  2. 代码宽度不能超过 80 个字符。(注释也不能)
  3. 代码编辑完后,要把 trailing spaces 去掉(Notepad++ 中 Edit--Blank Operations--Trim Trailing Space

一、C++ 语言部分

1)文件:

C 语言中,单词全小写,单词之间用 _ 连接,e.g. feature_detector.h, feature_detector.c

C++ 中,单词首字母用大写表示,单词之间不空格,e.g. FeatureDetector.hFeatureDetector.cpp

2)类:

  1. 定义声明:对于类的作用和内容进行简单的说明,用 //! remarks
  2. 命名规则:e.g. ComputingTemperature。(不同于 MFC,如 MFC 中 CZoomDlg,在类前加 C。而小组统一直接表示为 ZoomDlg。)

3)结构体:

C++ 中结构体不需要 typedef 便可直接当成类型使用,也就是说,下面两种是一样的

  1. // method 1
  2. struct ElecStateStruct {
  3. char *elec_name;
  4. char *elec_state;
  5. };
  6. // method 2
  7. typedef struct ElecStateStruct {
  8. char *elec_name;
  9. char *elec_state;
  10. } ElecStateStruct;

但推荐使用第二种

命名规则和类的一样。

4)函数和变量:

函数:

  1. 定义声明:在头文件(.h 文件)的类中,一般先写 private 型,再写 public 型。并先定义变量后定义函数。内容写于 .cpp 文件,并对其说明。
  2. 命名规则:currentTemperature( ... )filtering( ... )
  3. 注释:与 C 一致,须在函数前进行说明。说明函数功能、参数含义及返回值等,e.g.
  1. //! Function is used for feature point extraction,
  2. //! giving ... type variables,
  3. //! returns 1 means success, 0 means failure
  4. int extractionPoint( ... )
  5. {
  6. ...
  7. }

变量:

  1. 定义声明:与 C 一致。
  2. 命名规则:全局(e.g. _currentTemperature),局部(e.g. currentTemperature),函数内部的变量可以尽可能短。
  3. Qt 中信号和槽也可用 C 语言风格。比如:
  1. signals:
  2. void angle_resolution( double res );
  3. void angleResolution( double res );
  4. public slots:
  5. void on_angle_resolution( double res );
  6. void onAngleResolution( double res );

5)宏:

全大写,不以 _ 开头(避免重定义覆盖标准库或其他地方的宏),e.g. CURRENT_TEMPERATURE

三、程序排版规则

原则 0:

  1. 美观(不要吝惜你的空格和空行)
  2. 自身的一致性
  3. 大家的一致性(规范)

原则 1:

  1. 用等宽字体
  2. 不使用 tab 键,用 4 个空格代替(因为不同 IDE、编辑器、网页,对 tab 的显示宽度不一致。)
  3. 缩进(indent)用 4 个空格(Visual Studio 需要设置)

C Example:

  1. #include <stdio.h> // <-- 注意这里 <stdio.h> 前的空格
  2. #include <math.h>
  3. // <-- 【#include】s 后空行
  4. #define PI (3.1415) // <-- 最好都加上括号
  5. typedef struct PointCoordinate
  6. {
  7. int x ;
  8. int y;
  9. } Point;
  10. //! setting coordinate // <-- 函数说明
  11. Point set_point( int a, int b ); // <-- 函数声明,参数列表这里有空格
  12. //! get the area of the circle
  13. double get_area( int radius );
  14. void main()
  15. {
  16. // define the coordinate of the center, the radius and the area of a circle
  17. Point point_circle; // <-- 变量定义规则:小写,之间加下划线
  18. int radius_circle;
  19. double area_circle;
  20. // input the information of a circle // <-- 函数部分步骤意义说明规则
  21. printf( "please input point.x & point.y: \n" ); // <-- 函数调用,参数列表这里有空格
  22. scanf( "%d%d", &point_circle.x, &point_circle.y );
  23. printf( "please input the radius of the circle:\t" );
  24. scanf( "%d", &radius_circle );
  25. area_circle = PI * radius_circle * radius_circle;
  26. printf( "the area of a circle is: %lf\n", area_circle );
  27. }
  28. Point setPoint( int a, int b ) // <-- 函数定义,参数列表这里有空格
  29. {
  30. Ponit pt;
  31. pt.x = a;
  32. pt.y = b;
  33. return pt;
  34. }
  35. double getArea( int radius )
  36. {
  37. double S;
  38. S = PI * radius * radius;
  39. return S;
  40. }

加空格只是出于易读性的考虑,所以我们用 scanf( "%d", &radius_circle ); 而不是
scanf("%d", &radius_circle);。但如果行过长,就可以省略这些空格,比如:

  1. while ( 1 == scanf("%d", &num) ) { // 这里没空格
  2. printf( "%d\n", num ); // 这里有空格
  3. }

C++ Example:

  1. #include <iostream>
  2. #define PI (3.1415)
  3. #define MAX (300)
  4. //! basic class,2dim_point // <-- 对类的说明
  5. class Point
  6. {
  7. private: // <-- 先 private
  8. int x; // <-- 不能是 _x
  9. int y;
  10. public:
  11. int getX( ) { return x; } // <-- 极其简单的函数,可以放在一行
  12. int getY( ) { return y; }
  13. //! setting coordinate // <-- 函数说明(这个函数,就不该放在一行)
  14. void setPoint( int a, int b )
  15. {
  16. x = a;
  17. y = b;
  18. }
  19. //! calc distance from this point to another
  20. double distanceTo( Point &pt ); // <-- 长的函数都放在 cpp 文件
  21. };
  22. //! derived class circle
  23. class Circle : public Point
  24. {
  25. private:
  26. //! radius of a circle // <-- 变量说明格式
  27. int radius;
  28. public:
  29. //! set the size of the radius
  30. int setRadious( int r ) { radius = r; }
  31. void getRadious( ) { return radius; }
  32. //! get the area of the circle
  33. double getArea( ) { return PI * radius * radius; }
  34. };
  35. void main( )
  36. {
  37. // define a circle
  38. Circle circle1;
  39. // set up circle center & radius // <-- 对程序中的部分步骤说明
  40. circle1.setPoint(200, 250);
  41. circle1.setRadius(100);
  42. // output the X coordinate of the center of the circle1
  43. cout << "x = " << circle1.getX() << endl;
  44. // output the X coordinate of the center of the circle1
  45. cout << "the Area of Circle1 is " << circle1.getArea() << endl;
  46. }

正确和错误举例

  1. /*
  2. * 加足够的空格
  3. **/
  4. for(int i;i<count;i++) // WRONG
  5. for ( int i; i < count; i++ ) // CORRECT
  6. for ( int i; i < count; ++i ) // EVEN BETTER
  7. int max(int a,int b) // WRONG
  8. int max( int a, int b ) // CORRECT
  9. max(23,45); // WRONG
  10. max(23, 45); // WRONG
  11. max( 23, 45 ); // CORRECT
  12. max( 21, max(max(3,8), 34) ); // CORRECT,体会一下这些空格的有无
  13. show(); // CORRECT
  14. show( ); // CORRECT
  15. /*
  16. * 大括号的位置
  17. **/
  18. for ( int i; i < count; ++i ) // CORRECT,注意这里的空格
  19. {
  20. ...
  21. }
  22. for ( int i; i < count; ++i ) { // CORRECT
  23. ...
  24. }
  25. // 同理,正确的 while,if,do while 应为
  26. while ( CONDITION ) {
  27. ...
  28. }
  29. while ( CONDITION )
  30. {
  31. ...
  32. }
  33. if ( CONDITION ) {
  34. ...
  35. }
  36. if ( CONDITION )
  37. {
  38. ...
  39. }
  40. if ( CONDITION_1 ) {
  41. ...
  42. } else if ( CONDITION_2 ) {
  43. ...
  44. } else {
  45. ...
  46. }
  47. do {
  48. ...
  49. } while ( CONDITION );
  50. /*
  51. * 永远都加 {},哪怕只有一行代码,适用于 if、for、while 和函数声明+定义
  52. **/
  53. if ( FATAL_ERROR ) // WRONG
  54. return EXIT_FAILURE;
  55. if ( FATAL_ERROR ) { // CORRECT
  56. return EXIT_FAILURE;
  57. }
  58. int getX( ) return x; // WRONG
  59. int getX( ) { return x; } // CORRECT
  60. /*
  61. * 函数声明和调用的参数规范
  62. **/
  63. void func(); // WRONG
  64. void func2(int i, int j);
  65. void func( ); // CORRECT
  66. void func2( int i, int j );

其他一些说明

注释的放置

流程上的东西,夹在代码内,如:

  1. // set up circle center
  2. circle.setPoint( 200, 250 );
  3. // set up circle radius
  4. circle.setRadius( 100 );

补充说明性质的东西,放在行尾,如:

  1. fprintf( fp,
  2. "| %*i " // index
  3. "| %*s " // timestamp
  4. "| %*s%d%*s " // log level
  5. "| %*s%s%*s " // type (aligned to center)
  6. "| %-*s " // action
  7. "| %*s |\n", // messag
  8. ... );

对齐

通常不需要对齐,比如:

  1. int x0;
  2. double dx;

不必写成:

  1. int x0;
  2. double dx;

但如果很多东西,有一种莫名的联系,对齐则是上上之选,比如:

  1. /*
  2. * 对齐实例 1
  3. **/
  4. ust.time = parse8BytesToDouble(ba, c, f); c += 8;
  5. // q target
  6. ust.q_target[0] = parse8BytesToDouble(ba, c, f); c += 8;
  7. ust.q_target[1] = parse8BytesToDouble(ba, c, f); c += 8;
  8. ust.q_target[2] = parse8BytesToDouble(ba, c, f); c += 8;
  9. ust.q_target[3] = parse8BytesToDouble(ba, c, f); c += 8;
  10. ust.q_target[4] = parse8BytesToDouble(ba, c, f); c += 8;
  11. ust.q_target[5] = parse8BytesToDouble(ba, c, f); c += 8;
  12. /*
  13. * 对齐示例 2
  14. **/
  15. enum URFunctionCodes { /* 0-128d */
  16. // mb_req_pdu
  17. READ_COILS = 0x01, // read output bits
  18. READ_DISCRETE_INPUTS = 0x02, // read input bits
  19. READ_HOLDING_REGISTERS = 0x03, // read output registers
  20. READ_INPUT_REGISTERS = 0x04, // read input registers
  21. };
  22. /*
  23. * 对齐示例 3
  24. **/
  25. mcuAddr.insert( ROLL_PITCH_YAW, 0x000B );
  26. mcuAddr.insert( accX_accY_accZ, 0x000E );
  27. mcuAddr.insert( GyroscopeX, 0x0011 );

包括行末的 // 注释也最好对齐。
外,强烈建议 Qt 的信号和槽也对齐,不要使用

  1. connect(mcu, SIGNAL(mcuTimestamp(quint32)), this, SLOT(onMCUTimestamp(quint32)));

而是使用:

  1. connect( mcu, SIGNAL(mcuTimestamp(quint32)),
  2. this, SLOT(onMCUTimestamp(quint32)) );

参数列表也要对齐:

  1. // method 1
  2. return QString().sprintf( "%02d:%02d:%02d.%03d" // e.g. 01:23:45.678
  3. , dt.time().hour()
  4. , dt.time().minute()
  5. , dt.time().second()
  6. , dt.time().msec() );
  7. // method 2
  8. return QString().sprintf( "%02d:%02d:%02d.%03d", // e.g. 01:23:45.678
  9. dt.time().hour(),
  10. dt.time().minute(),
  11. dt.time().second(),
  12. dt.time().msec() );
  13. // but not this one
  14. return QString().sprintf( "%02d:%02d:%02d.%03d", // e.g. 01:23:45.678
  15. dt.time().hour(), dt.time().minute(),
  16. dt.time().second(), t.time().msec() );
  17. // and, of course, not this one
  18. return QString().sprintf( "%02d:%02d:%02d.%03d", dt.time().hour(),
  19. dt.time().minute(), dt.time().second(), t.time().msec() );

Q:如何写文档?
A:用 Markdown。

本文源码:https://gist.githubusercontent.com/district10/51005e331515b9272986/raw/CodingStyleOfChangshaTeam_CVRS.md

(要翻墙)

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注