• c++ 规范总结


    前言

    根据 c++代码规范1.1 整理

    头文件

    • 建议:每一个.cpp文件都要对应一个.h头文件
    • 头文件必须使用#define保护,统一包含它所需要的其它头文件,也不要求定义任何特别符号,不要使用 #pragma once
    • define保护的命名格式为<PROJECT>_<PATH>_<FILE>_H_

    • 建议:尽量避免使用前置声明,使用#include包含需要的头文件即可
    • 只有当函数只有10行甚至更少时才将其定义为内联函数
    • include顺序
    1. dir2/foo2.h (相关头文件)
    2. C 系统文件
    3. C++ 系统文件
    4. 其他库的 .h 文件
    5. 本项目内 .h 文件

    作用域

    • 禁止使用 using 指示(using-directive)
    • 禁止使用内联命名空间(inline namespace)
    • 禁止在命名空间 std 内声明
    • 禁止在头文件中使用命名空间别名
    • 在命名空间的最后注释出命名空间的名字
    • 命名空间中声明和定义不要使用缩进
    • 匿名命名空间的声明和命名空间的格式相同,在最后注释上 namespace,所有置于匿名命名空间的声明都具有内部链接性
    • 建议:非成员函数应尽量置于某个命名空间内或使用静态成员函数
    • 建议:尽可能小的作用域中声明变量, 离第一次使用越近越好,并在变量声明时初始化
    • 建议:循环语句内的变量尽量在外部声明
    • 全局变量,静态变量,静态类成员变量和函数静态变量,都必须是原生数据类型, 以及 POD 类型的指针、数组和结构体。

    • 禁止在构造函数中调用虚函数

    • 禁止在无法报出错误时进行可能失败的初始化,考虑使用 Init() 方法或使用工厂模式

    • 禁止在构造函数中抛出异常

    • 不要定义隐式类型转换

    • 如果需要就让你的类型可拷贝, 需要同时给出拷贝构造函数和赋值操作符的定义

    • 类型不需要拷贝, 需要将拷贝构造函数和赋值运算符禁用。

    • 仅当只有数据成员时使用 struct, 其它一概使用 class

    • 所有继承必须是 public

    • 如果基类有虚函数, 则析构函数也应该为虚函数

    • 所有数据成员都是私有的

    • 只有当所有父类除第一个外都是 纯接口类 时, 才允许使用多重继承

    • 除少数特定环境外, 不要重载运算符. 也不要创建用户定义字面量

    • 类定义一般应以 public 开始, 后跟 protected, 最后是 private

    • 建议:类中声明顺序为类型 (包括 typedef, using 和嵌套的结构体与类), 常量, 工厂函数, 构造函数, 赋值运算符, 析构函数, 其它函数, 数据成员

    函数

    • 建议:函数的参数顺序为: 输入参数在先, 后跟输出参数
    • 输入参数通常是值参或 const 引用, 输出参数或输入/输出参数则一般为非 const 指针
    • 输出参数禁止使用引用
    • 建议:函数尽量简短
    • 引用参数必须是const
    • 输入参数使用const指针,需要说明原因
    • 禁止虚函数使用缺省参数
    • 指针检查

    其他c++特性

    • 我们自己的代码中不要抛出异常,但是需要抓取第三方库的异常。捕获的异常需要处理,错误异常要输出日志
    • 除了项目中第三方库需要,我们禁止使用 RTTI
    • 不要使用流, 除非是日志接口需要. 使用 printf 之类的代替
    • 统一使用前置自增 (自减)
    • 强烈建议你在任何可能的情况下都要使用const
    • 使用<stdint.h>中长度精确的整形
    • 只在一个文件中使用的宏要在.cc文件中定义不要定义在头文件中
    • 指针变量定义时要初始化,指针销毁后要置nullptr,指针使用前要进行有效性判断
    • 指针使用前要使用if (nullptr == p) if (nullptr == p)进行防错处理
    • 指针初始化用nullptr
    • sizeof(varname)代替sizeof(type)
    • 禁止使用复杂的模板编程,参数不要超过3个.
    • 不要使用C++11,除非项目中第三方库需要

    命名约定

    • 命名要有一致性
    • 文件名要全部小写, 可以包含下划线,对于MFC项目中自动生成的文件名可不遵循本规则
    • 类, 结构体, 类型定义 (typedef), 枚举命名单词首字母均大写, 不包含下划线
    命名规则 类型+描述
    类型
    C :类
    Struct : 结构体
    P : typedef/using 指针类型
    En: 枚举
    
    • 变量命名采用匈牙利命名法
    • 函数命名采用帕斯卡命名法
    • const变量用const前缀
    • 命名空间命名全部小写,嵌套命名空间要注意冲突
    • 枚举类型使用En前缀,枚举值命名全大写ENUM_前缀_
    • _宏命名全大写下划线_分割

    注释

    • 文件头,函数/类说明使用/* /
    • *其他使用 ///* */, 统一就好
    • 每个文件开头加入文件注释,包括版权、说明、作者等信息,文件注释应当对文件的内容做一个大致的说明, 同时说明各概念之间的联系
    • 每个类的定义都要附带一份注释, 描述类的功能和用法,如果该类的实例可被多线程访问, 要特别注意文档说明多线程环境下相关的规则和常量使用,用一小段代码演示这个类的基本用法或通常用法
    • 类的声明和定义分开了(例如分别放在了 .h.cc 文件中), 此时, 描述类用法的注释应当和接口定义放在一起, 描述类的操作和实现的注释应当和实现放在一起
    • 函数的注释声明处描述函数功能; 定义处的注释描述函数实现;函数声明处注释函数的输入输出,参数是否可以为空等,函数定义处主要注释函数如何实现
    • 变量注释,变量名不足以说明用途,如果变量可以接受 NULL-1 等警戒值, 须加以说明;全局变量注释全局的原因
    • 复杂代码前添加注释,行注释空2格
    • TODO注释用来临时的, 短期的解决方案, 或已经够好但仍不完美的代码,为了在 "将来某一天做某事。格式使用全大写的字符串 TODO, 在随后的圆括号里写上你的名字, 邮件地址, bug ID
    • 弃用注释标记某接口为弃用状态,格式全大写的 DEPRECATED 在括号中留下您的名字, 邮箱地址以及其他身份标识
    • 修改他人注释格式//name 日期,修改原因

    格式

    • 建议:每一行代码字符数不超过 80
    • 只使用空格, 每次缩进 2 个空格
    • 函数返回值和函数名保持同一行,形参放不下可以分行
    • 函数调用要么在圆括号里对参数分行, 要么参数另起一行且缩进四格
    • 条件语句中不要在圆括号内使用空格. 关键字 ifelse 另起一行,如果有else if 在最后要加一个 else
    • 开关语句中case语句使用大括号,应该总是包含一个 default 匹配,如果 default 应该永远执行不到, 简单的加条 assert ,两条case之间没有break需要注释加以说明
    • 句点或箭头前后不要有空格. 指针/地址操作符 (*, &) 之后不能有空格
    • 声明指针变量或参数时, 星号与变量名紧挨
    • ==与常量比较时常量要写在前面
    • 布尔表达式中逻辑与 (&&) 操作符总位于行头
    • 只有在写 x = expr 要加上括号的时候才在 return expr; 里使用括号
    • 禁用 std::initializer_list 构造函数
    • 预处理指令不要缩进, 从行首开始,即使预处理指令位于缩进代码块中, 指令也应从行首开始
    • 访问控制块的声明依次序是 public:, protected:, private:, 不缩进
    • 命名空间内容不缩进
    • 不要使用 #pragma once

    ADD

    • 禁止使用魔数,使用sizeof、define
    • if else注释
  • 相关阅读:
    Jenkins安装
    Python操作yaml文件
    class 中构造函数与析构函数
    python发送邮件(yagmail模块)
    filter、map函数的区别
    python redis操作
    多个 python的pip版本选择
    python Excel操作
    python MD5操作
    缓存淘汰算法之LRU实现
  • 原文地址:https://www.cnblogs.com/xiongyungang/p/10860416.html
Copyright © 2020-2023  润新知