当前位置: 首页 > article >正文

C++:代码常见规范1

头文件包含

(1)先系统头文件,后用户头文件:这是一个良好的编程习惯。系统头文件通常包含标准库的定义,而用户头文件则包含项目特定的定义。将系统头文件放在前面可以避免因用户头文件中的定义与系统头文件冲突而导致的问题。

#include <iostream> // 系统头文件
#include "myheader.h" // 用户头文件

(2)当前目录:通常不需要使用./来指定当前目录,编译器默认会在当前目录查找头文件。但如果为了明确或避免潜在的路径问题,可以使用。

#include "xxx.h" // 默认在当前目录查找
// 或
#include "./xxx.h" // 明确指定当前目录

(3)上级目录:使用…/来指定上级目录中的头文件。

#include "../xxx.h"

(4)下级目录:使用相对路径来指定下级目录中的头文件。

#include "somedir/xxx.h"

(5)平行目录:使用…/来“跳出”当前目录,然后指定平行目录。
cpp

#include "../somedir/xxx.h"

(6)只引用需要的头文件

cpp和h文件常规规则

(1) 文件名命名规则:
C++源文件(.cpp文件)和头文件(.h文件)的命名通常采用大小写混合或小写混合的方式,以便于区分和识别。例如,DiyMainview.cpp和infoview.cpp都是有效的文件名。命名时应保持一致性,以便于项目的维护和管理。

(2) 头文件保护机制:
为了避免头文件被多次包含导致的重复定义问题,通常会在头文件中使用#ifndef预处理指令来控制代码块的包含。这种机制被称为“头文件保护”或“包含卫士”。示例如下:

#ifndef ADD_H
#define ADD_H
 
// 头文件的具体内容
 
#endif // ADD_H 结束

其中,ADD_H是一个唯一的标识符,用于标识这个头文件。在头文件的末尾,使用#endif指令来结束这个条件编译块,并在行尾添加注释以明确指出这是头文件保护的结束。

(3) 头文件#endif注释:
为了提高代码的可读性,建议在#endif指令后添加注释,明确指出这是哪个头文件保护块的结束。这有助于在查看代码时快速理解头文件的包含关系。

(4) 头文件内容组织顺序:
为了保持头文件的结构清晰,通常建议按照以下顺序组织内容:

包含指令:首先列出其他必要的头文件包含指令。
宏定义代码块:接着定义任何需要的宏。
全局变量和常量:然后声明全局变量和常量。
类型定义:紧接着定义任何需要的类型(如结构体、联合体、枚举等)。
类定义:定义类及其成员函数和成员变量。
内联函数:最后,可以定义内联函数(如果它们与类紧密相关,也可以放在类定义内部)。
(5) 源文件(.cpp文件)内容组织顺序:
源文件的内容组织同样需要清晰明了。通常建议按照以下顺序组织:

包含指令:首先列出所有必要的头文件包含指令。
宏定义:接着定义任何需要的宏(虽然宏定义通常放在头文件中,但在源文件中也可能需要)。
全局变量:然后声明和初始化全局变量(注意,全局变量的使用应尽量避免,因为它们可能导致代码难以维护和调试)。
函数定义:最后,按照逻辑顺序定义所有函数。

注释方面

1、文件头注释
作者:记录文件的创建者或主要维护者。
文件名称:明确文件的名称,便于识别和引用。
文件说明:简要描述文件的主要功能和用途。
日期和版本(可选):记录文件的创建日期、修改日期和版本号,有助于追踪文件的变更历史。
修改和维护说明(可选):提供关于如何修改和维护文件的指南或注意事项。
2、函数注释
关键函数注释:对于实现核心逻辑或关键功能的函数,必须添加详细的注释,说明函数的用途、输入参数、输出结果和可能的副作用。
参数注释:对于特别复杂的参数或需要特别注意的参数,应说明其目的、数据类型、取值范围以及由谁负责释放内存(如果适用)。
注释位置:除了特殊情况(如内联汇编代码或特定格式的宏定义),注释应写在代码行之前,而不是之后。这有助于保持代码和注释的同步更新。
条件编译注释:对于每个#else或#endif指令,应添加行末注释以说明条件编译块的结束。这有助于理解代码的编译逻辑。
关键代码注释:对赋值操作、函数调用、复杂表达式和分支逻辑等关键代码进行注释,说明其目的和作用。这有助于其他开发者快速理解代码的逻辑。
TODO注释:对于尚未实现完整的代码或需要进一步优化的代码,应添加// TODO …注释以标记待办事项。这有助于跟踪代码的改进需求。
DEBUG注释:对于仅用于调试目的的代码(如打印调试信息或临时变量),应添加// only for DEBUG注释以提醒其他开发者在发布版本时移除这些代码。
NOTE注释:对于需要引起特别关注的代码(如潜在的错误源、性能瓶颈或设计决策),应添加// NOTE …注释以提供额外的解释或说明。
代码块结尾注释:对于较大的代码块(如for、while、do-while循环),可以在结尾处添加// end for|while|do注释以明确代码块的边界。这有助于提高代码的可读性和可维护性。但请注意,这种注释在某些情况下可能是多余的(如代码块较短或结构清晰时),因此应根据实际情况灵活使用。

命名

  1. 同一性
    遵循基类或模块命名风格:在编写子模块或派生类时,应严格遵循其基类或整体模块的命名风格。这包括变量名、函数名、类名等的命名规则,以确保整个模块中的命名风格保持一致。
  2. 标识符组成
    采用英文单词或其组合:标识符应采用英文单词或其组合,以确保其直观、可拼读且易于理解。用词应准确,避免使用模糊或容易混淆的词汇。
    避免拼音命名:尽管拼音在某些情况下可能更方便,但为了避免潜在的误解和沟通障碍,应尽量避免使用拼音命名。
  3. 最小化长度与最大化信息量原则
    保持标识符意思明确:在命名时,应确保标识符的意思明确且易于理解。同时,为了提高代码的可读性,应尽量缩短标识符的长度,但不应牺牲其信息量。
    平衡长度与信息量:在保持标识符意思明确的前提下,通过合理的缩写和词汇选择来平衡长度与信息量。例如,可以使用“user”代替“userInformation”来表示用户信息,但前提是这种缩写在上下文中是清晰且易于理解的。
  4. 避免过于相似
    区分大小写:尽管C++等编程语言允许大小写敏感的标识符命名,但为了避免混淆和误解,应尽量避免使用仅靠大小写区分的相似标识符。
    使用不同词汇:对于具有不同含义的标识符,应使用不同的词汇来命名,以避免潜在的混淆。
  5. 避免重名
    不同作用域中的命名:在程序中,应避免在不同级别的作用域中使用完全相同的名称来命名变量。即使它们的作用域不同而不会发生语法错误,但这种做法仍然容易导致误解和混淆。
    使用命名空间:在大型项目中,可以使用命名空间来组织代码并避免命名冲突。这有助于保持代码的清晰和可维护性。
  6. 正确命名具有互斥意义的标识符
    使用反义词组:对于具有互斥意义的标识符,应使用正确的反义词组来命名。这有助于清晰地表达它们之间的关系和差异。
    保持一致性:在命名具有互斥意义的标识符时,应保持命名风格的一致性。例如,如果使用了“nMinValue”来表示最小值,则应使用“nMaxValue”来表示最大值。
  7. 避免名字中出现数字编号
    逻辑上的编号需求:尽管在某些情况下数字编号可能是必要的(如循环变量或数组索引),但在命名时应尽量避免使用无意义的数字编号。
    使用描述性词汇:为了代替数字编号,应使用更具描述性的词汇来命名变量或函数。这有助于提高代码的可读性和可维护性。

TCMR类

T类(简单数据类型类):
强调T类仅包含简单数据类型成员,且不对外部资源拥有所有权。
明确指出T类在析构过程中不会释放任何资源。
C类(从CBase继承的类):
强调C类必须从CBase(或类似基类)继承,且设计为非栈上分配对象。
建议使用智能指针或工厂模式等机制来管理C类对象的生命周期。
M类(接口类):
明确M类为纯接口类,不包含任何实现代码。
强调M类的函数命名应采用HandleXXX形式,遵循C++命名风格,避免Java风格或下划线风格。
建议M类的虚函数应设计为纯虚函数,以强制派生类实现。
R类(资源类):
指出R类通常代表系统固有资源,如文件句柄、网络连接等。
强调在开发代码中应尽量避免直接使用R类对象,而应通过封装或代理模式来管理资源。# 函数参数
(1)函数参数用a作为前缀。
(2)避免出现和匈牙利混合的命名规则如apBuffer名称。用aBuffer即可。
(3)函数参数比较多时,应考虑用结构代替。
(4)如果不能避免函数参数比较多,应在排版上可考虑每个参数占用一行,参数名竖向对齐。

函数参数

参数命名:
使用a作为函数参数的前缀,以保持一致性。
避免混合使用匈牙利命名法,如apBuffer应简化为aBuffer。
参数管理:
当函数参数较多时,考虑使用结构体或类来封装这些参数,以提高代码的可读性和可维护性。
如果无法避免多个参数,应在排版上使每个参数占用一行,并竖向对齐参数名,以增强代码的可读性。

成员变量

成员变量命名:
使用m作为成员变量的前缀。
避免混合使用匈牙利命名法,如mpBuffer应简化为mBuffer。

局部变量

循环变量和简单变量:
使用简单小写字符串命名循环变量和简单变量,如int i;。
指针变量:
使用p作为指针变量的前缀,如void* pBuffer;。

全局变量

使用g_作为全局变量的前缀,以明确标识其全局作用域。

类名

类名和对象名:
一般类和对象名应使用名词,以描述其代表的概念或实体。
成员函数名:
实现行为的类成员函数名应使用动词,以描述其行为或动作。
类的存取和查询成员函数名应使用名词或形容词,以描述其返回的属性或状态。

风格兼容性

对于移植的或开源的代码,可以沿用其原有风格,但应在项目文档中明确说明这些例外情况,以确保团队成员对代码风格有统一的认识。
在混合使用不同风格时,应尽量避免命名冲突和风格混乱,以保持代码的整体一致性和可读性。

Tab和空格

统一缩进:确保整个项目中缩进风格一致,要么全用Tab,要么全用空格,但推荐使用空格,因为空格在不同编辑器中的显示更一致。
避免多余空格:代码行结尾不应有多余空格,这可以通过代码编辑器或IDE的自动格式化功能来去除。
运算符周围空格:通常建议在运算符周围加上适当的空格以提高可读性,例如a + b而不是a+b。

类型定义中大括号

大括号位置:类、结构、枚举、联合的大括号应另起一行,这有助于提高代码的可读性和结构清晰度。
函数体大括号:函数体的大括号也应新起一行,并且{之前不应有缩进。这有助于区分函数签名和函数体。

函数

(1)函数体的{需要新起一行,在{之前不能有缩进。
(2)除了特别情况,函数体内不能出现两个空行。
(3)除了特别情况,函数体内不能宏定义指令。
(4)在一个函数体内,逻揖上密切相关的语句之间不加空行,其它地方应加空行分隔。
(5)在头文件定义的inline函数,函数之间可以不用空行,推荐用一个空行。

代码块

控制语句:if、for、while、do、try、catch等语句应自占一行,执行语句不得紧跟其后,且应始终使用大括号{},即使只有一条语句。
代码紧凑性:函数体内应避免不必要的空行,逻辑上密切相关的语句之间可以不加空行,其他地方应加空行分隔以提高可读性。

else

else风格:if语句如果有else语句,推荐使用} else {的形式编写在一行内,以保持代码的紧凑性。

代码行

单一职责:一行代码只做一件事情,这有助于提高代码的可读性和可维护性。
变量定义:多行变量定义时,为了美观可以将变量竖向对齐,但这不是强制的,取决于团队的约定。
行长度:代码行长度应控制在一定范围内(如80或120个字符),以确保在当前屏幕内可见。

switch语句

case对齐:case关键字应与switch对齐,以提高代码的可读性。
case代码块:case子语句如果有变量或复杂逻辑,应用{}包含起来。简单的case之间可以不加空行,复杂的case之间应考虑用空行分割。
default分支:为所有switch语句提供default分支,以防止未处理的情况。
break注释:如果某个case不需要break,一定要加注释声明,以避免潜在的逻辑错误。

循环

空循环:空循环可以使用for( ; ; )、while(1)或while(true),但推荐使用while(true)并加上适当的注释来说明这是一个无限循环。

继承:多继承中,基类应分行列出,以提高代码的可读性。单继承时,基类可以放在类定义的同一行或分行,取决于团队的约定。
虚函数重载:重载基类虚函数时,应在该组虚函数前加注释说明,例如// implement XXX。
友元声明:友元声明应放在类的末尾,以保持类的主体部分清晰。

宏定义结束:宏定义通常不需要用分号结束,除非它是为了模拟函数调用。
参数括号:函数宏的每个参数都要用括号括起来,以避免宏展开时的优先级问题。
无参数宏:不带参数的宏函数也应定义成函数形式,即使它实际上不接受任何参数。

goto

避免使用goto:尽量避免使用goto语句,因为它会使代码流程变得难以理解和维护。如果确实需要使用(例如跳出多层循环),应加上适当的注释来说明其用途。


http://www.kler.cn/a/536021.html

相关文章:

  • GB/T28181 开源日记[8]:国标开发速知速会
  • 【DeepSeek论文精读】2. DeepSeek LLM:以长期主义扩展开源语言模型
  • Android原生开发问题汇总
  • nuxt3中使用useFetch请求刷新不返回数据或返回html结构问题解决-完整nuxt3useFetchtch请求封装
  • 嵌入式八股文面试题(一)C语言部分
  • 哈希(Hashing)在 C++ STL 中的应用
  • 七。自定义数据集 使用tensorflow框架实现逻辑回归并保存模型,然后保存模型后再加载模型进行预测
  • Mac: docker安装以后报错Command not found: docker
  • ctf网络安全大赛python ctf网络安全大赛
  • 本文主要详细讲解ArcGIS中的线、多线段和多边形的结构关系。
  • Kafka 可靠性探究—副本刨析
  • 关于maven的java面试题汇总
  • 1 Java 基础面试题(上)
  • 物联网实训室解决方案(2025年最新版)
  • BUU26 [极客大挑战 2019]HardSQL1
  • Electron学习笔记,用node程序备份数据库(2)
  • Github 2025-02-07Java开源项目日报 Top9
  • 二叉树实现(学习记录)
  • 神经辐射场(NeRF):从2D图像到3D场景的革命性重建
  • Java面试题——事务
  • 【论文翻译】DeepSeek-V3论文翻译——DeepSeek-V3 Technical Report——第一部分:引言与模型架构
  • windows10环境下的Deepseek本地部署及接口调用
  • 网络安全威胁框架与入侵分析模型概述
  • 【PostgreSQL内核学习 —— (WindowAgg(三))】
  • golang命令大全12--命令速查表
  • Vue学习综合案例(四)