文章目录
一、命名规范
对于C++代码,每个人的风格和习惯各不尽相同,但是为了在项目中形成一个统一的,阅读性比较好的代码,这里参考了主要的开源代码、国内外各大厂以及以往的项目经验,这里对C++代码的命名进行了一个约定规范。
1、目录/文件
规范:使用小写字母、数字、下划线,多个单词间用下划线分隔。
原因:Windows
对目录和文件是大小写不区分的,而Linux
是大小写区分的。为了达到平台统一,这里规定都使用小写字母。
示例:
目录:app_cxx/proc_ui/src/firewall
文件:firewall_mgr.h、main.cpp、nfsv2.cpp
2、函数/接口
规范:使用小驼峰命名法。
原因:大部分著名的开源项目以及大厂对外提供的API都是这样的命名规范。
示例:
int test()
{
return 0;
}
int getLocalPort()
{
return 4335;
}
3、命名空间
规范:使用小写字母、数字、下划线,多个单词间用下划线分隔 (尽量只使用一个单词),
原因:
示例:
namespace logger
{
}
4、结构体/类
规范:使用大驼峰命名法,不包含下划线
原因:
示例:
struct SendData
{
};
class LoggerManager
{
};
5、变量
规范:使用小驼峰命名法。
(1)局部变量
示例:
void test()
{
int reqNum = 0;
}
(2)全局变量
补充:需要加前缀g_
示例:
int g_reqNum= 0;
(3)静态变量
补充:需要加前缀s_
示例:
void test()
{
static int s_reqNum = 0;
}
补充:当它同时也是全变量时使用全局变量的命名方式
示例:
int g_reqNum = 0;
(4)类成员变量
补充:需要加前缀m_
示例:
class ServerInfo
{
private:
int m_reqNum
}
(5)类静态变量
补充:需要加前缀s_
示例:
class ServerInfo
{
private:
static int s_reqNum;
}
(6)常量
补充:需要大写字母
原因:
示例:
const int MAX_NUM = 1024;
5、宏定义
规范:需要大写字母
原因:
示例:
#define CACHE_PATH "/data/cache"
6、枚举
规范:枚举名使用大驼峰命名法,枚举名建议带上class
类型,枚举值需要小写字母
原因:避免和宏定义冲突
示例:
enum class ResultType
{
ok,
open_fail,
unknown
};
二、注释规范
规范:尽量用/* */
进行注释,避免使用//。
原因:使用//
时,当不小心把其下面的一行代码回退到//
所在行时,如果没注意的话容易造成逻辑出错。
1、结构体/类注释
示例:
/**
* @brief 用户信息集合
*/
struct UserInfo
{
};
2、接口注释
示例:
/**
* @brief 查询用户信息
* @param username 用户名
* @return 用户信息
*/
UserInfo queryUserInfo(const std::string& username);
3、变量注释
示例:
int age = 0; /* 年龄 */
三、设计规范
1、声明/定义的位置?
规范:宏/枚举/变量/接口的声明和定义需要就近原则,能不跨文件就不跨文件。
原因:使得代码更加内聚,提升代码阅读的便利性。
示例:
在类DbMgr
中使用了宏定义:#define QUEYR_OK 1
- 如果该宏只在源文件
DbMgr.cpp
中使用,则宏定义放在DbMgr.cpp
中。 - 如果该宏仅仅作为返回值透露到外部模块,则宏定义放在
DbMgr.h
中。 - 如果该宏在其他若干业务中频繁使用,则宏定义放在公共的业务枚举定义文件中(可能如:
enum_def.h
)。
2、结构体(struct) or 类(class)?
规范:当定义的类型只是数据的集合且内部无复杂的处理逻辑时选择用struct
,反之如果更注重行为的封装则选择class
。
原因:struct
存在于栈上,用完即销毁。 注意: 由于栈有容量限制,避免在struct
中存放超大量的值类型。
示例:
struct UserInfo
{
UserInfo() : age(0), sex(0) {}
std::string username;
int age;
int sex;
};
class Grade
{
public:
std::vector<UserInfo> queryUserInfoList(const std::string& username);
};
3、单文件(.hpp) or 多文件(.h,.cpp) ?
规范:当模块只是一些信息的集合且无复杂内部逻辑可以使用.hpp
,反之使用多文件方式。
原因:模块逻辑复杂时,会经常变动,如果引用的外部模块多而使用.hpp
时,编译时间会变长。
示例:
单文件user_info.hpp
#pragma once
#include <string>
struct UserInfo
{
UserInfo() : age(0), sex(0) {}
std::string username;
int age;
int sex;
};
多文件grade.h
、grade.cpp
#pragma once
#include "user_info.h"
class Grade
{
public:
std::vector<UserInfo> queryUserInfoList(const std::string& username);
};
#include "grade.h"
std::vector<UserInfo> Grade::queryUserInfoList(const std::string& username)
{
return std::vector<UserInfo>{};
}
4、单例类
规范:把构造函数声明为私有。
原因:基于单例的定义,不允许类型不受控制的实例化。
示例:
头文件DbMgr.h
#pragma once
class DbMgr
{
private:
DbMgr();
public:
static DbMgr& getInstance();
};
源文件DbMgr.cpp
DbMgr::DbMgr() {}
DbMgr& DbMgr::getInstance()
{
static DbMgr s_instance;
return s_instance;
}