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(); };