ROS C++ 规范概要

1、动机linux

代码一致才能可读、联调、高效率、高复用、可移植性。express

 

2、命名方式数据结构

CamelCasedide

camelCased函数

under_scoredui

ALL_CAPITALSthis

2.1 Package命名方式:under_scoredlua

2.2 Topics / Services命名方式:under_scoredspa

2.3 Files命名方式:under_scoreddebug

好比:hokuyo_topurg_laser.cpp、hokuyo_topurg_laser.hpp

若是是类文件,那么命名方式迎合类名,好比:ActionServer类,那么action_server.h

2.3.1 lib命名方式:under_scored

不要在lib后面插入下划线,好比:

lib_my_great_thing ## Bad
libmy_great_thing ## Good

2.4 Classes / Types命名方式:CamelCased

好比:class ExampleClass

若是名字中有缩写,那么所有大写:class HokuyoURGLaser

2.5 Function / Methods

函数名称和类的方法:camelCased,参数采用:under_scored

2.6 Variables

通常采用under_scored。合理描述变量,不要表达不清。

迭代变量,好比:for(int i = 0; …),能够用短变量i, j, k;应用顺序保证为i,j,k。

STL 迭代变量,必须标明STL变量的类型如:

std::list<int> pid_list;
std::list<int>::iterator pid_it;

STL迭代器的能够用自身类型表示

std::list<int> pid_list;
std::list<int>::iterator int_it;

2.6.1 Constant命名方式:ALL_CAPITALS

2.6.2 Member variables命名方式:under_scored_

2.6.3 Global variables命名方式:g_under_scored

2.7 Namespaces命名方式:under_scored

 

3、License statements

在头文件与源文件的开头都要包含Copyright,好比:

Copyright (c) 2019 Fujian(Quanzhou)-HIT Research Institute of Engineering and Technology All rights reserved.

解释一下,©是版权的意思,也能够写成(c);2019表示代码完成时间;Fujian(Quanzhou)-HIT Research Institute of Engineering and Technology 泉州工研院;All rights reserved表示保留全部权利。

也能够写成:

Copyright (c) 2019-2020 Fujian(Quanzhou)-HIT Research Institute of Engineering and Technology All rights reserved.

2019-2020表示意思完成时间是2008年,最近一次修订在2011年。

 

4、Formatting

IDE应该能够处理大量的格式化事情。建议采用VSCode。

缩进为2个空格,不用tab键。Namespaces不缩进

好比:

if(a < b)
{
  // do stuff
}
else
{
  // do other stuff
}

单行能够不用括号,符号链接以下:

if(a < b)
  x = 2 * a;

if(a < b)
{
  for(int i = 0; i < 10; i++)
    PrintItem(i);
}

下面给出一个完整的例子:

/*
 * A block comment looks like this...
 */
#include <math.h>
class Point
{
public:
  Point(double xc, double yc) :
    x_(xc), y_(yc)
  {
  }
  double distance(const Point& other) const;
  int compareX(const Point& other) const;
  double x_;
  double y_;
};
double Point::distance(const Point& other) const
{
  double dx = x_ - other.x_;
  double dy = y_ - other.y_;
  return sqrt(dx * dx + dy * dy);
}
int Point::compareX(const Point& other) const
{
  if (x_ < other.x_)
  {
    return -1;
  }
  else if (x_ > other.x_)
  {
    return 1;
  }
  else
  {
    return 0;
  }
}
namespace foo
{
int foo(int bar) const
{
  switch (bar)
  {
    case 0:
      ++bar;
      break;
    case 1:
      --bar;
    default:
    {
      bar += bar;
      break;
    }
  }
}
} // end namespace foo

4.1 每行字符数:120个字符之内

4.2 头文件格式

防止重复调用,采用如下格式:

#ifndef PACKAGE_PATH_FILE_H
#define PACKAGE_PATH_FILE_H
...
#endif

 

5、文档

全部程序必须有文档,并且采用doxygen创建文档。

 

6、控制台输出

尽可能不采用printf与cout,采用 rosconsole做为输出。

 

7、宏

避免使用宏定义,与inline与const不一样,宏既不是类型,也不是做用域。

 

8、预处理指令(#if vs. #ifdef)

对于条件编译,咱们采用#if,不采用#ifdef。

好比:

#ifdef DEBUG
        temporary_debugger_break();
#endif

若是咱们想关闭DEBUG,那么会输入:

cc -c lurker.cpp -DDEBUG=0

若是采用:

#if DEBUG
        temporary_debugger_break();
#endif

即便DEBUG没有定义,也能够用。

 

9、输出参数

用于输出的参数采用指针,而不是引用。好比:

int exampleMethod(FooThing input, BarThing* output);

 

10、Namespaces

很是建议你们使用命名空间来指定代码的做用域,根据package的名字来命名namespace

不采用using-directive,好比

using namespace std; // Bad, because it imports all names from std::

采用using-declarations,好比:

using std::list;  // I want to refer to std::list as list
using std::vector;  // I want to refer to std::vector as vector

 

11、继承

采用virtual表示多态,不采用多重继承

 

12、异常处理

异常处理采用error-report机制,而不采用返回整形值。好比:

在document记录在packages中function/method产生的所有异常。

不采用在destructors中调用throw。

不采用在callback方法中调用throw。

若是采用在package中采用错误代码,而非异常处理,请保持代码始终如一。

12.1 异常处理注意事项:

当您的代码能够被异常中断时,您必须确保在堆栈变量超出范围时将释放您保留的资源。 特别是,必须释放互斥锁,而且必须释放堆分配的内存。 

 

十3、Enumerations(枚举类型)

用namespace控制枚举类型:

namespace Choices
{
  enum Choice
  {
     Choice1,
     Choice2,
     Choice3
  };
}
typedef Choices::Choice Choice;

 

十4、Globals(全局类型)

不采用全局变量以及全局函数。

 

十5、Static class variables(静态成员变量)

不采用静态成员变量。

 

十6、调用exit()函数

仅在程序出口调用exit()函数。

在lib中不采用exit()函数。

 

十7、Assertions()

 采用assert检查前提条件,数据结构完整性以及内存分配器的返回值。 assert比编写条件语句更好,条件语句不多(若是有的话)被执行。

不采用直接调用assert(),而采用ros/assert.h

/** ROS_ASSERT asserts that the provided expression evaluates to
 * true.  If it is false, program execution will abort, with an informative
 * statement about which assertion failed, in what file.  Use ROS_ASSERT
 * instead of assert() itself.
 * Example usage:
 */
   ROS_ASSERT(x > y);
/** ROS_ASSERT_MSG(cond, "format string", ...) asserts that the provided
 * condition evaluates to true.
 * If it is false, program execution will abort, with an informative
 * statement about which assertion failed, in what file, and it will print out
 * a printf-style message you define.  Example usage:
 */
   ROS_ASSERT_MSG(x > 0, "Uh oh, x went negative.  Value = %d", x);
/** ROS_ASSERT_CMD(cond, function())
 * Runs a function if the condition is false. Usage example:
 */
   ROS_ASSERT_CMD(x > 0, handleError(...));
/** ROS_BREAK aborts program execution, with an informative
 * statement about which assertion failed, in what file. Use ROS_BREAK
 * instead of calling assert(0) or ROS_ASSERT(0). You can step over the assert
 * in a debugger.
 * Example usage:
 */
   ROS_BREADK();

不要在assert中作工做; 只检查逻辑表达式。 根据编译设置,可能没法执行断言。

 

十8、Testing

 见gtest.

 

十9、Portability(能够移植性)

目前ros支持linux与XOS之间的移植,须要注意:

(1)不采用uint,采用unsigned int

(2)调用isnan()使用std::isnan()

 

二10、Deprecation(移除不用的代码)

若是移除包中的头文件,应在头文件加入警告:

#warning mypkg/my_header.h has been deprecated

若是移除函数,添加不推荐使用属性:

ROS_DEPRECATED int myFunc();

若是移除一个类,请移除其构造函数和任何静态函数:

class MyClass
{
public:
  ROS_DEPRECATED MyClass();

  ROS_DEPRECATED static int myStaticFunc(); 
};
相关文章
相关标签/搜索