C++设计开发规范(10):编码规范

本文详细介绍了C++编码规范,包括书写风格、模板书写、注释、标识符命名、常量、变量、类型转换、内存管理、控制语句和函数等多个方面。规范强调了良好的代码风格、避免使用魔法数字、合理使用注释、正确处理内存分配和释放,以及优化循环结构等最佳实践。
 
“编码风格应该尽可能地合理、简洁”
要求类的书写风格如下:
   //单继承,写成一行
   classs ClassName : public BaseClassName
   //多重继承,写成多行
classs ClassName :
public BaseClassName1,
public BaseClassName2
   {
       public:
       ////////////////////////////////////////////////////////////////////////////////
       //ctor & dtor
       ClassName();
       virtual ~ ClassName();
       public:
       ////////////////////////////////////////////////////////////////////////////////
       //public overrides,from BaseClassName1
       virtual void Func1_1();
       ////////////////////////////////////////////////////////////////////////////////
       //public overrides,from BaseClassName2
       virtual void Func2_1();
       ////////////////////////////////////////////////////////////////////////////////
       //public virtual method
       virtual void Func3_1();
       ////////////////////////////////////////////////////////////////////////////////
       //public methods
                     void Func1();
       protected:
////////////////////////////////////////////////////////////////////////////////
       // protected overrides,from BaseClassName1
       virtual void Func1_1();
       ////////////////////////////////////////////////////////////////////////////////
       // protected overrides,from BaseClassName2
       virtual void Func2_1();
       ////////////////////////////////////////////////////////////////////////////////
       // protected virtual method
       virtual void Func3_1();
       ////////////////////////////////////////////////////////////////////////////////
       // protected methods
                     void Func1();
       private:
       ////////////////////////////////////////////////////////////////////////////////
       // private methods
                     void Func1();
       ////////////////////////////////////////////////////////////////////////////////
       // private Fields
                     type m_field1;
type m_field2;
       }
       要求将花括号单独写在一行。
       //不好
          if(DoSomething()){
              …
          }
        //不好
          if(DoSomething()){…}
          //好
if(DoSomething())
{
    …
          }
要求if、for、do、while、case、switch、default等语句自占一行,且if、for、do、while 等语句的执行语句部分无论多少都要加括号 {}
要求程序块要采用缩进风格编写,缩进的空格数为4个。
要求相对独立的程序块之间、变量说明之后必须加空行。
× 不要把多个短语句写在一行中,即一行只写一条语句。
要求较长的语句(>80字符)要分成多行书写。
要求循环、判断等语句中若有较长的表达式或语句,则要进行适应的划分,长表达式要在低优先级操作符处划分新行,操作符放在新行之首。
   例如,
if ((taskNo < MAXTASKNUMBER)
    && (taskNo>0))
      {
          …
      }
例如,
//不好
rect.Length = 0; rect.Width = 0;
//好
rect. Length = 0; 
rect. Width = 0;
要求 注意运算符的优先级,并用括号明确表达式的操作顺序,避免使用默认优先级。
例如,
//不好
high << 8 | low
a | b && a & c
a | b < c & d
//好
word = (high << 8) | low
if ((a | b) && (a & c))
if ((a | b) < (c & d))
要求在形式参数之间的逗号后添加空格。
void Foo(char bar,int x,int y);//不好
      void Foo(char bar, int x, int y);//好
l 推荐不要在实际参数之间添加空格。
    Foo( MyChar,0,1 );//不好
Foo(MyChar,0,1);//好
       × 不要在函数和’(‘之间添加空格。
Foo ();//不好
              Foo();//好
       × 不要在’[‘之后和’]’之前添加空格。
X = dataArray[ index ];//不好
              X = dataArray[index];//不好
l 推荐在二元操作符之前或之后添加空格。
           if(x==y)// 不好
              // 好
if(x == y)
a = 0;
a = b;
a >>= 2;
a = b ^ 2;
       × 不要在一元操作符之前或之后添加空格。
if(! x)//不好
// 好
              if(!x)//好
if (a->b)
*p = 'a';
flag = !isEmpty;
要求模板函数 /类的泛型类型的关键字使用typename,不要使用class。
    //不好
       template<class T>
       inline Max(const T& x1, const T& x2)
    //好
       template<typename T>
       inline Max(const T& x1, const T& x2)
要求模板函数 /类的书写风格如下:
       template<typename T>
       class MyTemplate
{
       void Method1();
       template<typename TParam>
       void Method2(const TParam& param);
}
template<typename T>
       inline Max(const T& x1, const T& x2)
l 推荐不要在代码实现中添加注释。
       例外:说明某个复杂的算法
要求向外部模块 / 包暴露的接口、类、函数、变量等添加注释。
    更多的注释方法请参考 附录B
    例如,
       //! Call native method
       extern void CallNativeMethod();
       /*! /interface IExporter
          For the usage of exporting the file to PDF/PS/XML etc.
       */
       interface IExporter
       {
              …
       }
       /*! /class Exporter
          For the usage of exporting the file to PDF/PS/XML etc.
       */
       class Exporter : public IExporter
       {
              …
       }
要求遵守 命名规范。
× 不要使用魔数 (Magic Number) 。
要求常量的命名全部使用大写。
    例如,
    const int MaxPath = 256;//不好
const int Max_Path = 256;//不好
const int maxpath = 256;//不好
    const int MAXPATH = 256;//好
× 不要使用 #define而是使用const来定义常量。
    例如,
    #define MAXPATH 256//不好
    const int MAXPATH = 256;//好
要求使用枚举值/static const来定义类中的常量。
    例如,
    //不好
    class Document
    {
    public:
        Document()
            : VIID(1000)
{
}
        const int VIID;
}
    //好
    class Document
    {
    public:
        enum {VIID = 1000};
}
//
class Document
    {
    public:
        static const int VIID = 1000;
}
l 推荐不要使用全局变量。
l 推荐不要使用static局部变量。 
要求所有的成员变量/局部变量都要进行初始化。
例如,
class Documents
{
public:
       Documents()
              : m_documentCount(0) //初始化
{
}
void NewDocument(const wchar_t* fileName)
{
       bool successful = false;//初始化
}
private:
       int m_documentCount;
}
l 推荐变量的声明和初始化能够一次完成的尽量一次完成。
       //不好
       int childCount = 0
       childCount = pParent->GetChildCount();
       //好
int childCount = pParent->GetChildCount();
× 不要使返回一个局部变量的引用。
       例如,
       Child* CreateChild()
       {
              Child child;
              Return &child;//不好
       }
l 推荐变量只在使用之前进行定义,不要把变量定义都放在函数的开头。
       //不好
       void BubbleSort(int dataArray[],int count)
       {
              int i = 0;
              int j = 0;
              int temp = 0;
              for(i = count-1;i  > 1; ++i)
              {
                     for(j = 0; j < i; ++ j)
                     {
                     }
              }
       }
       //不好
       void BubbleSort(int dataArray[],int count)
       {
              for(int i = count-1;i > 1; ++i)
              {
                     for(int j = 0; j < i; ++ j)
                     {
                     }
              }
       }
× 不要使用布尔变量直接和 0、1进行比较。
       //不好
       if (flag == 0)
       if (flag == 1)
       //好
       if (flag)
       if (!flag)
l 推荐判别指针变量是否为空采用下面的方式。
       if (p)
       if (!p)
× 不要使用强制类型转换,如果会损失精度或导致不可预测的行为。
× 不要强制转化 const指针变量到non-const。
l 推荐使用const_cast和static_cast来实行强制类型转换,如果强制类型转换是必需的。
l 推荐尽量少使用指向指针的指针或指针数组。
× 不要使用 malloc/free,而要使用new/delete来申请/释放内存。
    //不好
       int* p = (int*)malloc(sizeof(int));
       free(p);
       p = 0;
       //好
       int* p = new int;
       delete p;
       p = 0;
要求delete一块内存的时候,将指向这块内存的指针设置为空。
    //不好
       delete p;
    //好
       delete p;
       p = 0;
要求使用new[]分配的内存,要使用delete[]进行释放。
       //不好
       int* p = new int[100];
       delete p;
       p = 0;
    //好
       int* p = new int[100];
       delete[] p;
       p = 0;
× 不要跨模块释放和释放内存。
    不好的方式,例如:
       //模块A中
Page* AllocPage()
{
       …
    return new Page;
}
//模块B中
Page* pNewPage = AllocPage();
delete pNewPage;
pNewPage = 0;
l 推荐少使用/不使用goto语句。
要求优先使用前置的++/--,如果前置和后置的++/--的结果一致。
    //不好
       for(int i = 0;i < MAXCOUNT; i++)
       //好
       for(int i = 0;i < MAXCOUNT; ++i)
要求将最短的循环放在最外层、最长的循环放到最内层,如果存在多重循环。
       //不好
       for(int row= 0; row < 100; ++row)
{
       for(int col= 0; col < 5; ++ col)
       {
       }
}
//好
       for(int col= 0; col < 5; ++ col)
{
       for(int row= 0; row < 100; ++row)
       {
       }
}
       要求将逻辑判断移到循环体的外面,如果循环体内部存在逻辑判断且循环次数很大。
       //不好
       for(int i = 0; i < LARGECOUNT; ++i)
{
       if (condition)
              DoSomething();
       else
              DoOtherThing();
}
//好
if (condition)
{
for(int i = 0; i < LARGECOUNT; ++i)
DoSomething();
}
else
{
for(int i = 0; i < LARGECOUNT; ++i)
DoOtherThing ();
}
       要求每个case语句的结尾都要加上break。
              例外:由于逻辑需要,需要重叠多个case分支。
要求default语句的结尾都要加上break。
要求在构造函数中对成员进行初始化,成员初始化的顺序同成员的声明顺序。
    例如,
 class PointF
       {
       public:
              //好
              PointF ()
                     : m_x(0.0F),
                      m_y(0.0F),
{…}
//不好
              PointF ()
                     : m_ y(0.0F),
                      m_x(0.0F),
{…}
 
              private:
                     double m_x;
                     double m_y;
       }
要求在operator=中检测右操作符和当前对象指向同一个地址。
       例如,
       Color& operator=(const Color& other)
{
              if ((void*)&other == this) {return *this;}    //好
              …
              }
要求在operator=重载中返回*this。
    例如,
struct Color
{
public:
Color& operator=(const Color& other)
{
              if ((void*)&other == this) {return *this;}    //好
              …
              return *this;                                              //好
}
private:
       char m_componets[8];
}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值