C++编码规范

来源:互联网 发布:苹果手机淘宝没有了 编辑:程序博客网 时间:2024/06/05 10:37

C++编码规范

来源于VC知识库视频C++编码规范,并整理成一份笔记。

  • 头文件尽可能依赖于前置申明

【优势】较小的文件依赖,节约编译时间,更加明确类的依赖关系

#ifndef _MYCLASS_H_#define _MYCLASS_H_class myClass1;class myClass2;class myClass{    //TODO:};#endif
  • 函数的参数申明顺序,输入参数在前,输出参数在后。
    输入参数一般为传值和常数的引用,输出参数或输入输出参数一般为非常数指针。
    【优势】通过位置明确函数参数的作用,有利于代码的合并。
class foo;void func(int nInputNum,           foo& rInputFoo,          foo* pInputFoo,          void* output);
  • 头文件包含的顺序(之间用空行)
    类对应头文件
    C系统库文件
    C++系统库文件
    其他系统库文件
    本项目内头文件

【优势】增加代码可读性,利于代码的合并

class <foo/public/class.h>class <stdio.h>class <math.h>class <iostream>class <vector>class <projClass1.h>class <projClass2.h>
  • 局部变量的初始化
    尽可能小的作用域中申明变量,离第一次使用的位置越近越好。明确包含使用的顺序。

【优势】使代码易读

int nNum = 0;float fNum;fNum = 0;
  • 局部类的初始化
    一个类的局部变量会默认做一次构造函数和析构函数,应注意避免多次的初始化和析构。
class Foo;Foo f1;for (int i = 0 ; i < 1000; ++i){    Foo f2; //会降低效率,多次初始化和析构    f1.doSomething();}
  • 类的初始化
    养成良好的类成员申明的习惯。
class CStudent{public:    CStudent() : m_id(0) {}private:    size_t m_id;};
  • 类的拷贝构造和=运算符重载
    注意深浅拷贝
class CStudent{public:    CStudent(const CStudent& rStu)    {        m_name = new char[strlen(rStu.m_name) + 1];        strcpy(m_name, rStu.m_name);        }    CStudent& operator=(const CStudent& rStu)    {        if (this == &rStu)        {            return *this;        }        delete[] m_name;        m_name = new char[strlen(rStu.m_name) + 1];        strcpy(m_name, rStu.m_name);        return *this;    }private:    char* m_name;}
  • 结构体和类
    仅当只有数据成员时才使用结构体,其余情况一般使用类。结构体默认是public,类默认是private。
    同时结构体也支持初始化构造和析构。
struct stStudent{    char name[128];    size_t id;    stStudent()    {        memset(name, 0, sizeof(name));        id = 0;    }};//也可以直接初始化struct stStudent stu = {0};
  • 操作符重载
    操作符重载能带给我们便利,但是同时会使我们代码变得不直观。因此我们应该尽可能定义多的方法来取代操作符重载。
class CString{public:    CString& equals(const CString& rStr);    CString& operator=(const CString& rStr);};int main(){    CString str1("hello");    CString str2;    str2.equals(str1); //instead of str2 = str1;    return 0;}
  • 将类的成员进行私有化
    应尽可能将类的成员定义为private,并通过set和get函数对外公开。

【优势】有利于代码的封装性和代码的调试。

class CStudent{public:    void set(const char* name) { strcpy(m_name, name); }    char* get() { return m_name; }private:    char* m_name;}
  • 类中的申明顺序
    声明的顺序一般为,public,protected,private
    在每个块中,成员函数需申明在成员变量之前,其他的申明顺序如下:
    typedef和enums
    常量
    构造函数
    析构函数
    成员函数,包括静态成员函数
    数据成员,包括静态数据成员
class CText{public:    //typedef    typedef vector<int> vecInt;    //常量    const int kNum;    //构造和析构    CText();    ~CText();    //普通方法    void doSome();    //静态成员    static int m_sId;    //静态方法    static int getID();protected:private:};
  • 编写短小的函数
    如果没有特殊的需求,函数代码的长度应该控制在40行左右,如果过长的情况下且不影响程序的运行时,可将长函数进行切割。

【优势】提取重复的代码,易于他人的阅读和修改,容易发现和定位bug

  • 输入的引用参数需要添加const
    如果传入的参数是引用型,建议添加const

【优势】约束了调用行为,自解释了参数的作用

bool equal(const CPoint& p){    return (x == p.x) && (y == p.y);}
  • 不使用函数的重载,而直接使用函数的名称进行区分
    没有特殊要求尽量不进行函数的重载,而直接使用函数的名称进行区分,过多的函数重载会使调用者无从选择。
class CStudent{    CStudent* GetStudent(const int nID);    CStudent* GetStudent(const char* chName);    CStudent* GetStudentFromID(const int nID);    CStudent* GetStudentFromName(const char* chName);};
  • 禁止使用缺省参数
    函数的参数应该添加缺省的参数

【优势】可以避免错误的理解

//避免使用的函数方法CStudent* GetStudentFromID(const int nID,                            bool isFromLocale = true);CStudent* GetStudentFormName(const char* chName,                             bool isFromLocale = true);
  • 禁止使用RTTI
    不使用dynamic_cast

【优势】利用类型号和virtual关键字可以实现运行时确定类本身的功能

  • 自增自减操作符重载
    前置的自增自减效率高于后置自增自减,特别是对于迭代器。
vector<int> vecInt(10, 10);for (vector<int>::iteartor it = vecInt.begin();     it != vecInt.end();     ++it){    //TODO:}
  • 尽可能的使用const
    如果函数不会修改传入的引用后指针类型的参数,返回的参数应该为const;
    不修改数据的函数应定义为const;
    如果成员变量在构造函数初始化之后不会改变,应声明为const;

【优势】约束变量的操作行为

//类作为函数参数的时候,应该使用引用或者指针,减少类的拷贝构造,增加效率bool isEqual(const Class& a, const Class* b);
  • 0,NULL和初始化
    整数使用0
    浮点数使用0.0
    指针使用NULL
    字符串使用”\0”
int nNum = 0;double dNum = 0.0;char* ptr = NULL;char array[128] = "\0";
  • sizeof的用法
    应尽可能使用sizeof(变量名)来代替sizeof(类型)

【优势】防止变量类型在运行时改变

 struct stBook {     int BookId;     char BookName[128]; }; int main() {     stBook book;     memset(&book, 0, sizeof(book)); //not sizeof(stBook)     return 0;}
  • 变量的命名
    不要定义一些无法解释的名称变量
    尽量避免错误的拼写或者拼写不完整
    类名称全部以大写开头
    结构体、枚举全部以大写开头
    变量命名一律以小写开头
    类成员变量带m_开头
    常量以k开头
    函数名称以大写开头,每个单词首字母第一个大写
    类的存取函数,存函数以Set开头,取函数以Get开头
    枚举类型的值全部大写,每个单词以下划线隔开
    全局变量以g开头
    宏定义全部字母大写,每个单词以下划线分割
//无法解释的名称变量int a, b, c;//错误的拼写或者拼写不完整int err, nam, cot;//类名以大写开头class CStudent;//结构体和枚举大写开头struct StBook;//变量命名使用小写bool isTrue;int nNum;//类成员变量private:    int m_id;//常量const int kCount;//函数void GetMyName();//存取函数int GetIndex();void SetIndex(int nIndex);//枚举类型的值enum Week{    W_MONDAY = 0,    W_TUESDAY,    ...}//全局变量int g_nCount = 0;//宏定义#define MAX_LEN 100
  • 匈牙利的命名规则
    类型+作用名称
//指针int* pInt;//函数void fnDoSomething();//无效void vData;//句柄HANDLE hBitMap;//长整型long lDays;//布尔bool bVisible;//浮点型或者文件float fNum;//双字DWORD dwStyle;//字符串string strName;//短整型int nNum;//双精度double dRate;//计数int cIndex;//字符(通常用c)char chByte;char cByte;//整型(通常是n)int iNum;int nNum;//字节byte byData;//字WORD wChar;//无符号unsigned uSize;
0 0
原创粉丝点击