ns-3的c++代码规范
该文档 txt 版本详见: http://download.csdn.net/detail/barcodegun/3704860
ns-3学习交流:
[email protected]
一、 统一风格的重要性
特别注意: 以下风格并不是C++的强制标准,而是为了便宜于他人阅读,
便于不同开发者之间的交流以及其他开发人员的进一步开发、维护而设立的共同规范。
一个程序的开发,一般都需要一个团队来完成,不同开发者之间需要共同的代码规范,才能融合到一起。同时,开发者和维护者往往不是同一个人。
写出来的程序,要让他人能看懂,一定要遵循一个共同的规范,因此,好的代码,一定要让人能看懂。
二、 命名
1. 函数名、方法名、类名的命名方法为:
a. 单词首字母大写,其他字母都小写;
b. 即使是缩写,如EDCA,也改成 Edca
举例:
my computer => 命名为: MyComputer
MAC, PHY => 命名为: Mac, Phy //不要把所有字母都大写,即使这是一个缩写。
IP => 命名为 Ip
如: class MyClass
{
...
};
bool IsTrue ()
{
...
}
c. 函数定义、调用的时候,函数名和()之间留一个空格。 如: IsTrue ()
2. 变量名的命名
a. 首字母小写
变量 user name => 命名为: userName
//这样做的好处是: 用户看到userName就这知道这是一个变量名,看到UserName就知道这是一个类名
b. 全局变量以 g_ 开头
static int g_aStaticVar = 100;
int g_aGlobalVar = 1000;
c. 类的成员变量以 m_ 开头
class MyClass
{
void MyMethod (int aVar); //方法名MyMethod
int m_aVar;
//类成员变量 m_aVar
static int m_anotherVar;
};
d. 自定义类型以 _t 结尾
如:
typedef unsigned int uint8_t;
typedef int NewTypeOfInt_t;
e. 变量的定义及赋初值:
e1. 每个变量单独一行定义,不推荐 int width,height 这种定义方法,推荐用两行定义:
int width;
int height;
e2. 变量定义推荐赋初值(在main函数中直接赋初值,在类中用构造函数赋初值);
e3. 对于意义明显如width的变量定义可以不用注释,意义不明显的变量,一定要进行注释;
e4. 变量赋值的时候,推荐等号两边都有一个空格(不是强制,仅仅只是为了便于阅读)
如:
int x = 0; //车辆的当前位置
int length = 5; //车辆的长度,单位为米
g. 常量名全部用大写,多个单词以下划线 _ 隔开
const uint8_t PORT_NUMBER = 17;
以上port number 端口号,由于是常量,因此全大写并以下划线隔开: PORT_NUMBER
3.名字的选取方法
a. 变量、函数、方法、类等的命名都要用英文名,不要用中文拼音;
b. 名字的选取,最好是一看就知道意思。如果不能这样,一定要进行注释;
如类的名字一般为
class Packet
class Buffer
class Mac
等
函数、类的方法命名,一般基于动词、形容词命名,如:
bool IsTrue ()
double GetX ()
void DoDispose ()
void ClearArray ()
等
c. 长的具有说明意义的名字比短的不具有意义的名字要好;
比如: size 比 sz要好。
d. 遵循常用习惯:
如 temp 表示临时变量
i j k 表示循环变量
e. 函数、类的方法返回值为bool型,函数名以 Is 或 Has 开头,如:
bool IsTrue ()
bool HasWord (char *value) //查询是否有相关的单词
三、代码布局
a. 缩进两个空格
b. 为了增加可读性,每条语句都单独占用一行;
c. 条件、循环语句,其中 { 以及 } 单独占用一行;
如果 只有一条语句,也可以全部都写在一行。
d. 每一个变量声明单独占用一行;
e. 函数在声明的时候,声明语句写在同一行:
如: double GetX ();
函数在定义的时候,返回值一般单独占用一行,如:
double
GetX ()
{
return m_aVar;
}
f. 变量应该在需要的时候才声明,声明的时候推荐赋初值;
g. 在类中声明变量名,变量名可以对齐,也可以不对齐,
变量类型与变量名之间不能有tab字符(可以在Linux vim中把tab转换为两个空格字符)
int varOne;
double varTwo; // OK (未对齐)
int varOne;
double varTwo; // also OK (对齐)
例:
void //返回类型一般占一行
Foo (void)
{ // {单独占用一行。如果条件、循环语句内只有一条语句,也可以所有语句占用一行
if (test) // if缩进两个空格,函数名与 () 之间留有一个空格
{
// do stuff here
}
else
{
// do other stuff here
}
//if语句执行完毕,所以应该空一行,再写for语句
for (int i = 0; i < 100; i++) // 等号、小于号等运算符号两边各有一个空格, 分号后面有一个空格
{
// do loop
}
while (test)
{
// do while
}
do
{
// do stuff
} while ();
}
四、 文件格式及代码组织
一、类声明和成员函数定义分离
以MyClass类为例,
在 my-class.h 中对类及其成员函数进行声明,
在 my-class.cc 中定义成员函数的实施方法。
二、 ns-3 中的做法
1. my-class.h
a.照本宣科的内容:
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) YEAR COPYRIGHTHOLDER
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: MyName
*/
解释说明:
第一行确保使用emacs编辑器的开发者能够正确打开文件。
紧接着确保下面的代码在GPL版权下,即开源。
注意,不推荐使用"All Rights Reserved"
b. #ifndef的用法:
#ifndef MY_CLASS_H
#define MY_CLASS_H
...
#endif /* MY_CLASS_H */
解释说明:
a. MY_CLASS_H 即 my-class.h ,比如 DropPacket 类,则用 DROP_PACKET_H
b. 上面#ifndef ... #endif 的作用:
简单地说,就是为了防止该头文件被重复包含。
比如: 有一个头文件 drop-packet.h
packet.h 中使用 #include "drop-packet.h"
packet-metadata.h 中也使用 #include "drop-packet.h"
而主文件中包含了 packet.h以及 packet-metadata.h ,这样 drop-packet.h就被重复包含了。
如果在 drop-packet.h中使用了 #ifndef ... 上面的语句,则程序可以正确执行,不用担心重复包含的问题。
c.例:
#ifndef MY_CLASS_H
#define MY_CLASS_H
namespace n3 {
class MyClass
{
public:
MyClass ();
int DoSomething (int firstParam);
private:
void MyPrivateMethod (void);
int m_myPrivateMemberVariable;
};
} // namespace ns3
#endif /* MY_CLASS_H */
2. my-class.cc
a.和上面.h照本宣科的内容相同
b. 正式代码
#include "my-class.h"
namespace ns3 {
MyClass::MyClass ()
{}
...
} // namespace ns3
五、 ns-3中的注释
ns-3中的注释与传统的注释有一定的区别,主要是因为ns-3用Doxygen程序生成帮助文档,
所以ns-3的注释要遵循Doxygen的规范。
doxygen语法详见:
http://www.doxygen.org/index.html
如:
/**
* \param firstParam a short description of the purpose of this parameter
* \returns a short description of what is returned from this function.
*
* A detailed description of the purpose of the method.
*/
int DoSomething (int firstParam);
将在帮助文档中生成:
A detailed description of the purpose of the method.
Parameters:
firstParam a short description of the purpose of this parameter
Returns:
a short description of what is returned from this function.
六、其他
1. 常引用语法:
void MySub (const T&); // 推荐
void MySub (T const&); // 不推荐
2.函数名和 () 之间留一个空格
void MySub (const T&); // 推荐
void MySub(const T&); // 不推荐
这个规则在函数定义、函数调用的时候都适用。
3.类声明和成员函数定义分离
即分为 .h 和 .cc 两个文件
4. 如果不想在类中使用默认的复制构造函数,则定义为私有
private:
ClassName (const Classname&);
ClassName& operator= (const ClassName&)
5. 对类成员变量的存取,推荐使用类的成员函数存取,设置用Set开头,获取用Get开头
如:
在my-class.cc 文件中:
void MyClass::SetWidth (double value)
{
m_width = value;
}
void MyClass::GetWidth ()
{
return m_width;
}