1禁止在头文件中定义变量

2禁止在extern “C”中包含头文件,否则会导致extern “C”嵌套,嵌套太多导致编译错误

3每个模块提供多个.c文件,在同一目录下,目录名为模块名,并提供一个.h文件

4.如果一个模块包含多个模块,则每个模块提供一个.h文件名为子模块名

5.头文件排版方式:1.按字母升序

                             2.将不稳定(常修改)的放在前面

6.一个函数仅完成一项功能。重复代码尽量写成函数

7.避免函数过程,最好不超过50行。

8.代码嵌套不超过4层

9.函数不变参数要写为const

10.避免使用全局变量和静态变量

11.函数参数个数不超过5个。检查参数的有效性(是否为NULL)

12.命名规则

l         unix风格:每个单词小写,并用下划线分开my_name

l         windows风格:每个单词首字母大写 MyName

l         文件命名采用小写字符

l         全局变量g_    静态变量s_

(5)宏:大写单词_大写单词

13:将宏定义的放在大括号内

14:用const替代宏定义

15.inline函数的优点:

l         编译时不用展开,代码Size小,

l         可以加断电,易于定位问题。例如对于引用计数加减的时候

l         编译时编译器做语法检查

16.注释在代码上面(用空行隔开)或右边

 

17

文件头注释:

/**

*@file          文件名

*@brief        功能描述

*@version   版本

*@author           作者

*@date       创建日期

*/

 

函数头注释:

/**

*@descriotion

*@param a

*@param b

*@return c

*/

 

18程序块采用缩进风格编写,每级缩进为4个空格。

19相对独立的程序块之间、变量说明之后必须加空行

20.一条语句不能过长,拆分

l         换行时要增加一级缩进

l         低优先级操作符处划分新行;换行时操作符应该放下来放在新行首

l         换行时一个完整的语句放在一行

l         一行只写一条语句

21.两个以上的关键字、变量、常量进行对等操作时,操作符前后应该加空格

l         符号、操作符后面加空格

l         if、for、while、switch后加空格。

l         !、~、++、--、&后不加空格

l         注释符与注释内容之间加空格

 

22一组相关的整数用enum

23.不相关的常量,即使取值相同,也必须分别定义

24变量使用时才声明并初始化

25.避免构造函数做复杂的初始化,

可以使用init函数():

l         需要提供初始化返回信息

l         数据成员初始化可能抛异常

l         数据成员初始化失败会造成该类对象初始化失败,引起不确定状态

l         数据成员初始化依赖this指针:构造函数没结束,对象就没有构造出来,构造函数内不能使用this成员

l         数据初始化需要调用虚函数。在构造函数和西沟函数中调用虚函数,会导致未定义行为。

26初始化列表严格按照成员声明顺序初始化

27.使用c++风格的类型转换

const_cast 移除const属性的转换。避免使用

dynamic_cast下行转换,基类指针转换为子类指针。类型检查,建议调试代码中使用

static_cast 一般的强制转换

reinterpret_cast 转换不相关的类型,避免使用。

28.内联函数小于10行。且不要有循环、递归、虚函数。内联函数在头文件中声明

29.尽量用const引用取代指针。引用比指针安全,一定非空,一定不会指向其他目标。不需要检查非法NULL指针

30,一定要写构造函数。

构造函数参数列表的初始化

Message():

a(0),

b(“”),

c(NULL)

{
}

30.如果不定义构造、拷贝、赋值、析构等。编译器会自动生成。

默认的构造和赋值函数只是将元对象的成员简单赋值给目的对象,即浅拷贝(shallow copy)。使元对象和目的对象的成员指向同一内存,导致资源重复释放。自动生产的析构函数是空的,不能释放已盛情的堆内存。如果不需要拷贝够咱函数和赋值函数,将其声明为private

31..让operator=返回*this的引用,使之能连等。并检查是否是自赋值

String&String::operator=(const String &rhs)

{

     If(this!=&rhs)

{

         delete [] data;

         data=new char[strlen(rhs.data)+1];

         strcpy(data,rhs.data);

}

return *this;

}

 

32基类指针执行删除操作时,基类的析构函数设为共有虚拟的。保障派生类析构函数被调用

33虚函数不使用默认参数,因为是动态绑定的,而默认参数是编译时静态绑定的,所以最终执行的函数是一个定义在派生类,但却使用了基类的默认参数值的虚函数

 

class A

{

 

public:

   virtual void display(const string& str="Base")

   {

      cout<<str<<endl;

   }

};

class B:public A

{

public:

   virtual void display(const string& str="Derived")

   {

   cout<<str<<endl;

   }

};

 

A* a=new B();

a->display();//调用派生类display,调用基类默认形参,输出Base,

delete a;

a=NULL;

 

34.绝不重新定义(隐藏)继承而来的非虚函数。因为无法动态绑定

35.避免派生类中定义与基类同名但参数类型不同的函数,引起虚函数调用失败

36.派生类重定义的虚函数也要声明virtual

37.仅在输入参数类型不同个,功能相同时重载函数

 

38建议4.7 使用重载以避免隐式类型转换

说明:隐式转换常常创建临时变量;如果提供类型精确匹配的重载函数,不会导致转换。

示例:

class String 

{

    //…

    String( const char* text );      //允许隐式转换

};

bool operator==( const String&, const String& );

//…代码中某处…

if( someString == "Hello" ) {... }

上述例子中编译器进行隐式转换,好像someString == String( "Hello")一样,形成浪费,因为并不需

要拷贝字符。使用操作符重载即可消除这种隐式转换:

bool operator==( const String& lhs, const String& rhs );     //#1

bool operator==( const String& lhs, const char* rhs );       //#2

bool operator==( const char* lhs, const String& rhs );       //#3

 

39使用名字空间进行归类,避免符号冲突cout<<space_a::a+space_b::a;

40不要在头文件中或者#include之前使用using指示符

 

41不要在extern "C"内部使用#include包含其他头文件

在C++代码中调用C的库文件,需要用extern "C"来告诉编译器:这是一个用C写成的库文件,用C的方式来链接它们。

严格的讲,只应该把函数、变量以及函数类型这三种对象放置于extern "C"的内部。

如果把#include指令放在extern "C"里面,可能会导致extern "C"嵌套而带来如下几个风险:

extern "C"嵌套过深,导致编译错误

extern "C"嵌套后,改变其他某些文件的编译链接方式

 

42构造函数初始化列表在同一行或按4格缩进并排几行

43类的声明按照一定的次序和规范进行。建议的次序如下:

  按照存取控制特性段排序:public、protected、private,如果没有可以忽略。这个排序是让声

明的时候使用者首先看到最关心的特性(对外接口)。

  在每一段中按照如下顺序声明(先定义后续用到的类型,常量和enums;然后定义行为(构造,析构,

成员函数),最后定义成员变量):

1.  typedefs和enums;

2. 常量;

3. 构造函数;

4. 析构函数;

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

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

 

44 使用‘//’注释方式,而不是‘/* */',容易产生交叉错乱

 

45不直接使用C++的基本数据类型,不要假定其存储尺寸长度

说明: C++标准没有明确基本数据类型的大小与存储格式,  这些基本类型包括: short,  int, long, lo

long, float double等。这些基本数据类型在不同的编译器中,实现有所不同,如:

long类型在32位编译模式下为4字节长度,在64位编译模式下为8字节长度。

所以建议不要直接使用基本数据类型。推荐如下两种使用方式:

1、重定义基本数据类型

typedef int32_t int;

typedef int64_t long long;