zoukankan      html  css  js  c++  java
  • ROS C++ 规范概要

    一、动机

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

    二、命名方式

    CamelCased

    camelCased

    under_scored

    ALL_CAPITALS

    2.1 Package命名方式:under_scored

    2.2 Topics / Services命名方式:under_scored

    2.3 Files命名方式:under_scored

    比如: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

    三、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年。

    四、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

    五、文档

    所有程序必须有文档,而且采用doxygen建立文档。

    六、控制台输出

    尽量不采用printf与cout,采用 rosconsole作为输出。

    七、宏

    避免使用宏定义,与inline与const不同,宏既不是类型,也不是作用域。

    八、预处理指令(#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没有定义,也可以用。

    九、输出参数

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

    int exampleMethod(FooThing input, BarThing* output);

    十、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

    十一、继承

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

    十二、异常处理

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

    在document记录在packages中function/method产生的全部异常。

    不采用在destructors中调用throw。

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

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

    12.1 异常处理注意事项:

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

    十三、Enumerations(枚举类型)

    用namespace控制枚举类型:

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

    十四、Globals(全局类型)

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

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

    不采用静态成员变量。

    十六、调用exit()函数

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

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

    十七、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中做工作; 只检查逻辑表达式。 根据编译设置,可能无法执行断言。

    十八、Testing

     见gtest.

    十九、Portability(可以移植性)

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

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

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

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

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

    #warning mypkg/my_header.h has been deprecated

    如果移除函数,添加不推荐使用属性:

    ROS_DEPRECATED int myFunc();

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

    class MyClass
    {
    public:
      ROS_DEPRECATED MyClass();
    
      ROS_DEPRECATED static int myStaticFunc(); 
    };
  • 相关阅读:
    类型"ImportMeta"上不存在属性"env"(Property 'env' does not exist on type 'ImportMeta')
    微信小程序开发常见问题
    js构建沙箱环境sandbox
    js 判断两个对象是否相同
    js判断类型方法
    初学knockoutjs记录4——Computed observables依赖监控(1 Using computed observables使用计算监控属性)
    初学knockoutjs记录3——Observables监控属性(2 Observable Arrays 监控数组)
    初学knockoutjs记录2——Observables监控属性(1 创建带有监控属性的view model)
    初学knockoutjs记录1——入门介绍及下载安装
    C、C++、JAVA编译器是如何处理未经初始化的变量的。
  • 原文地址:https://www.cnblogs.com/hgl0417/p/10514791.html
Copyright © 2011-2022 走看看