• C++编码规范


    命名规范

    通用命名规则

    类型名

    类型名(类、结极体、类型定义(typedef)、枚举)以大写字母開始并混合大写和小写。如

    Line, SavingsAccount

    变量名

    变量名必须以小写字母開始并混合大写和小写, 如

    line, savingsAccount

    函数名

    函数名必须以小写字母的动词開始并混合大写和小写。如:

    getName(), computeTotalWidth()

    常量名

    常量名(包含枚举值)必须所有大写并下面划线分隔。如

    MAX_ITERATIONS, COLOR_RED, PI

     

    类的私有变量

    类的私有变量必须下面划线_作为后缀。如:

    class SomeClass {

      private:

        int length_;

    }

     

    名字空间

    名字空间的命名必须所有小写,如:

    model::analyzer, io::iomanager, common::math::geometry

     

    接口类

    接口类的命名曾经缀的大写I后跟类名, 如:

    class IFoo

    {

    public:

           virtual ~IFoo(){};

           virtual void dooo() = 0;

    }

     

    模板类型名

    模板类型命名必须是单个大写字母,如:

    template<class T> …

    template<class C, class D> …

    缩略语

    缩略语不必都是大写,如:

    exportHtmlSource(); // 这样不好: exportHTMLSource();

    openDvdPlayer();    // 这样不好: openDVDPlayer();

     

     

    全局变量

           全局变量命名规则同变量名,仅仅是全局变量必须总是以::来引用,如:

    ::mainWindow.open(), ::applicationContext.getName()

    通用变量

    通用变量(如函数參数)的命名应该就是它的类型,且首字母小写。如:

    void setTopic(Topic* topic)  // 这样不好: void setTopic(Topic* value)

                                // 这样不好: void setTopic(Topic* aTopic)

                                // 这样不好: void setTopic(Topic* t)

     

    void connect(Database* database)  // 这样不好: void connect(Database* db)

                                     // 这样不好: void connect (Database* oracleDB)

     

    文件名称

    文件名称所有小写。C++文件以.cpp结尾,头文件以.h结尾,文件名称与文件中类的名字同样。

    非通用命名规则

    非通用变量(如局部变量)能够是这样:

      Point  startingPoint, centerPoint;

      Name  loginName;

    函数名中不应该再包含对象名,如:

    line.getLength();   //这样不好: line.getLineLength();

     

    特殊命名规则

    指针命名:

    Line* line;   // 这样不好: Line* pLine;

                // 这样不好: Line* linePtr;

     

    枚举常量能够使用一个公共的类型名作为前缀。如:

    enum Color {

      COLOR_RED,

      COLOR_GREEN,

      COLOR_BLUE

    };

     

    bool类型的变量和函数返回值是bool的函数以is为前缀来命名,如:

    isSet, isVisible, isFinished, isFound, isOpen

    在某些情况下。有些比is前缀更适合(has, can, should),如:

      bool hasLicense();

      bool canEvaluate();

      bool shouldSort();

     

    当有属性的情况下。使用get/set来存取,如:

    employee.getName();

    employee.setName(name);

    matrix.getElement(2, 4);

    matrix.setElement(2, 4, value);

     

    想要计算什么能够使用compute,如:

    valueSet->computeAverage();

    matrix->computeInverse()

     

    想要想找什么能够使用find, 如:

    vertex.findNearestVertex();

    matrix.findMinElement();

     

    对象的初始化能够使用initialize ,而不要使用init

     

    GUI组件的命名要把组件类型放到变量的后面,如:

    mainWindow, propertiesDialog, widthScale, loginText,

    leftScrollbar, mainForm, fileMenu, minLabel, exitButton, yesToggle 等。

     

    复数形式变量命名使用例如以下:

    vector<Point>  points;

    int            values[];

     

    变量具有前缀n表明这个变量代表了对象的个数。如:

    nPoints, nLines

     

    No为后缀的变量表明第几个对象,如:

    tableNo, employeeNo

     

    迭代变量应该被命名为i, j, k等,如:

    for (int i = 0; i < nTables); i++) {

      :

    }

    for (vector<MyClass>::iterator i = list.begin(); i != list.end(); i++) {

      Element element = *i;

      …

    }

     

    对称的命名:

    get/set, add/remove, create/destroy, start/stop, insert/delete,

    increment/decrement, old/new, begin/end, first/last, up/down, min/max,

    next/previous, old/new, open/close, show/hide, suspend/resume, etc.

     

    命名时避免使用缩略语

     

    禁止否定的bool变量名。如:

    bool isError;  //这样不好: isNoError

    bool isFound;  //这样不好: isNotFound

     

    异常类命名以Exception作为后缀,如:

    class AccessException

    {

      :

    }

     

    注:

           1) 不要使用匈牙利命名法

             2) Windows定义了非常多原有内建类型的同义词(非常反感。easy导致类型混乱),如DWORD、HANDLE等等。在调用Windows API时这是全然能够接受甚至鼓舞的,但在非调用API时尽量使用原来的C++类型,比如。使用const TCHAR *而不是LPCTSTR;原因:有助于代码的移植。特别是server后台开发者,尽量使用标准的C++类型。

     

    代码书写规范

    C++是个特性极其丰富而复杂的语言。本文档旨在提供怎样编写高质量C++程序的建议。

    原则

    正确、简单和清晰第一

           软件简单为美(Keep it Sample Software, KISS原则),正确优于速度。简单优于复杂。清晰优于机巧。安全优于不安全。

           要避免出现代码“坏味道”。摘录自《重构 改善既有代码的设计》

     

    代码的坏味道

    1.       反复代码

    2.       过长函数

    3.       过大类

    4.       过长參数列

    5.       发散式变化

    6.       霰弹式改动

    7.       依恋情结

    8.       数据泥团

    9.       基本型别偏执

    10.   switch惊悚现身

    11.   平等继承体系

    12.   冗赘类

    13.   夸夸其谈未来性

    14.   令人迷惑的临时值域

    15.   过度耦合的消息链

    16.   中间转手人

    17.   狎昵关系

    18.   异曲同工的类

    19.   不完好的程序库类

    20.   纯稚的数据类

    21.   被拒绝的遗赠

    22.   过多的凝视

     

    详细内容请參考《重构 改善既有代码的设计》, 在写代码的过程中,加红的几个是特别须要注意的

     

    编译设置

    在高警告级别进行编译。使用VC编译器应将警告级别打到最高4级,并设置将警告作为错误

    宁要编译时和连接时错误,而不要执行时错误

    项目设置include, lib路径使用相对路径,不要使用绝对路径

    debug编译生成的是名称后加d 。如(debug是xxxd.exe, release是xxx.exe)

     

    头文件

    正确使用头文件可令代码在可读性、文件大小和性能上大为改观。

    头文件以.h作扩展名

    #define保护

    全部头文件 都应该使用#define防止头文件被多重包括(multiple inclusion),命名格式为:<PROJECT>_<PATH>_<FILE>_H_

    为保证唯一性,头文件的命名应基于其所在项目源码树的全路径。

    比如。项目foo中的头文件foo/src/bar/baz.h按例如以下方式保护:

    #ifndef FOO_BAR_BAZ_H_

    #define FOO_BAR_BAZ_H_

     …

    #endif // FOO_BAR_BAZ_H_

    注:不要使用#pragma once来防止反复包括。由于该指令是vc特有的,它是一个编译器指令,其他的编译器不保证能支持它,而#ifndef是语言层面的, 仅仅要是支持c++的编译器, 都支持,跨平台,兼容性更好。

    头文件依赖

    使用前置声明(forward declarations)尽量降低.h文件里#include的数量,加快编译速度。

     

    内联函数

    叧有当函数叧有10行甚至更少时才会将其定义为内联函数(inline function)。

    注:滥用内联将导致程序变慢。

     

    函数參数顺序

    定义函数时。參数顺序为:输入參数在前。输出參数在后。

     

    包括文件的名称及次序

    将包括次序标准化可增强可读性、避免隐藏依赖(注:隐藏依赖主要是指包括的文件编译)

    头文件包括次序例如以下:C库、C++库、其它库的.h、项目内的.h。

    实现文件(如dir/foo.cpp)包括次序例如以下:

    dir2/foo2.h(优先位置。详情例如以下)

    C系统文件

    C++系统文件

    其它库头文件

    本项目内头文件

    在包括文件中不要使用.(当前文件夹)和..(父文件夹)。如:

    #include “../abc.h” // 不要这样使用

     

    作用域

    命名空间

    在.cpp文件里,同意甚至提倡使用未具名命名空间。以避免执行时的命名冲突: namespace {

     // .cc 文件里 // 命名空间的内容无需缩进

     enum { UNUSED, EOF, ERROR }; // 常常使用的符号

    bool AtEof() { return pos_ == EOF; } // 使用本命名空间内的符号EOF

    } // namespace

    然而,不特定类关联的文件作用域声明在该类中被声明为类型、静态数据成员或静态成员函数,而不是未具名命名空间的成员。

    像上文展示的那样,不具名命名空间结束时用凝视// namespace标识。

    不能在.h文件里使用未具名命名空间。

    不要在头文件里或者#include之前使用using namespace

     

    局部变量

    将局部变量尽可能置于最小作用域内,在声明变量时就将其初始化。

     

    全局变量

    禁止class类型的全局变量

    内建类型的全局变量是同意的。

    当然多线程代码中很数全局变量也是被禁止的。

    永远不要使用函数返回值来初始化全局变量。

     

    原因:c++标准在全局变量的构造函数、析构函数和初始化顺序上没有保证。因此每次生成都可能会有变化,从而导致难以觉察的BUGS。

     

    对于全局的字符串常量,使用C风格的字符串。而不要使用STL的字符串:

    const char kFrogSays[] = “ribbet”;

     

    尽管同意在全局作用域中使用全局变量,使用时务必三思。

    大多数全局变量应该是类的静态数据成员,或者当其叧在.cpp文件里使用时,将其定义到未具名命名空间中

    注:静态成员变量视作全局变量。所以,也不能是class类型!

     

    假设一定要使用全局变量,请使用设计模式中的单件模式(singleton模式)。

     

    C++类

    用小类取代巨类

    构造函数

           类构造函数的初始化列表中成员变量初始化的顺序应该与在h头文件里声明的顺序一致。

    不要在构造函数体里进行赋值操作。

           对单參数构造函数使用C++keywordexplicit。

     

    虚拟函数

    避免在构造函数和析构函数中调用虚拟函数

     

    继承

             多用组合。少用继承

     

    接口

             接口定义例如以下:

    class IFoo

    {

    public:

             virtual ~IFoo(){};

             virtual void dooo() = 0;

    };

    即含有纯虚函数,且实现虚析构函数的类。

    接口类主要是为实现多态的。

     

    操作符重载

             尽量不要使用操作符重载

     

    存取控制

             将数据成员私有化。并提供相关存取函数

     

    声明次序

           在类中使用特定的声明次序:public:在private:之前。成员函数在数据成员(变量)前。

    定义次序例如以下:public:、protected:、private:,假设那一块没有,直接忽略就可以。

    每一块中,声明次序一般例如以下:

    1) typedefs和enums;

    2) 常量;

    3) 构造函数;

    4) 析构函数;

    5) 成员函数,含静态成员函数;

    6) 数据成员,含静态数据成员。

     

    编写短小函数

    函数体尽量短小、紧凑,功能单一

     

    智能指针

           假设确实须要使用智能指针的话,scoped_ptr全然能够胜任。

    在很特殊的情况下,比如对STL容器中对象。你应该仅仅使用std::tr1::shared_ptr,不论什么情况下都不要使用auto_ptr。

     

    引用參数

             引用传递的參数必须加上const。假设要将參数传出,请使用指针。

     

    缺省參数

    禁止使用缺省函数參数。

     

    异常

    不要使用C++异常。

    异常会导致程序控制流通过查看代码无法确定:函数有可能在不确定的地方返回,从而导致代码管理和调试困难。

    异常的有用性可能会刺激开发者在不恰当的时候抛出异常。戒者在不安全的地方从异常中恢复。

     

    执行时类型识别RTTI

    禁止使用RTTI, 单元測试程序除外。

     

    类型转换

    使用C++风格的类型转换, 不要使用C风格的类型转换。

    1) static_cast:和C风格转换相似可做值的强制转换,或指针的父类到子类的明白的向上转换;

    2) const_cast:移除const属性。

    3) reinterpret_cast:指针类型和整型或其它指针间不安全的相互转换。仅在你对所做一切了然于心时使用。

    4) dynamic_cast:除測试外不要使用,除单元測试外,假设你须要在执行时确定类型信息,说明设计有缺陷(參考RTTI)。

     

    前置自增和自减

           对简单数值(非对象)来说,两种都无所谓,对迭代器和模板类型来说,要使用前置自增(自减)。

     

    const的使用

           在不论什么能够使用的情况下都要使用const。

     

    预处理宏

    使用宏时要慎重,尽量以内联函数、枚举和常量取代之。字符串化(##)除外;

     

    0和NULL

             整数用0,实数用0.0,挃针用NULL,字符(串)用’/0’。

     

    sizeof(sizeof)

             用sizeof(varname)取代sizeof(type);

     

    Boost库

             仅仅使用Boost中被认可的库。

     

    STL容器

    默认时使用vector。否则。选择其它合适的容器

    用vector和string取代数组

    使用vector(和string::c_str)与非C++API交换数据

    在容器中仅仅存储值和智能指针

    用push_back取代其它扩展序列的方式

    算法和比較器的參数应多用函数对象少用函数

     

    DLL

    分配和释放内存

    要避免在不同的模块中分配和释放内存。比如,在DLL中分配的内存,必须仍由该DLL来负责释放,而不要交给调用该DLL的程序来释放。

     

    全局变量

           不要在DLL中使用全局变量,除非你明白能这样使用。

    线程

    尽量降低共享数据

           在多线程设计中。尽量要降低线程间共享的数据

     

     

    使用SVN规范

    提交代码必须写提交日志

    提交代码,代码必须是debug和release都可编译执行的

    在改动代码之前。首先update

     

    凝视规范

           本凝视以简单为主。风格遵循doxygen格式,以便于借助doxygen工具可直接生成文档。

    凝视的确非常重要。但最好的代码本身就是文档(自文档),凝视是为别人(下一个须要理解你的代码的人)而写的,认真点吧。那下一个人可能就是你。

     

    凝视风格

           统一使用// 来凝视,即双斜杠 + 空格

     

    文件凝视

           通常。.h文件要对所声明的类的功能和使用方法作简单说明。.cc文件包括了很多其它的实现细节或算法讨论,假设你感觉这些实现细节或算法讨论对于阅读有帮助。能够把.cc中的凝视放到.h中,并在.cc中指出文档在.h中。

    不要单纯在.h和.cc间复制凝视,复制的凝视偏离了实际意义。

     

    // @brief 简要描写叙述

    // @author 作者

    类凝视

    // 类描函数凝视

           // 函数描写叙述

           // @param 參数 描写叙述

           // @return 返回值 描写叙述

    变量凝视

           凝视占一行, 不要这样:

           Point centerPoint; // 中心点

           应该这样:

           // 中心点

           Point centerPoint;

     

    C++命名规则

  • 相关阅读:
    项目依赖库列表文件requirements.txt生成和使用
    pymysql执行sql语句无效问题
    Prometheus
    关于在安装wampserver出现“由于找不到msvcr110.dll”的问题的解决办法
    安装centos8和Window10出现的一些问题和解决方法
    LeetCode833题:字符串中的查找与替换
    Pycharm中github的使用(只有链接供自己学习使用)
    机器学习《西瓜书》的学习笔记——机器学习使用的领域
    机器学习中数理统计与参数估计的相关基础概念
    怎样在Anaconda中的某一个环境中安装Python的相关包(pypyodbc)
  • 原文地址:https://www.cnblogs.com/brucemengbm/p/6890019.html
Copyright © 2020-2023  润新知