2 函数或者类定义后要加空行;函数内或者类内逻辑上不相关的语句要加空行
3 函数或者类花括号格式
{
}
别的花括号格式 {
}
也有所有花括号用
{
}风格的 两种风格都可以用
4 后面加空格 if switch case for do while 逗号操作符, 或者分号(init; cond; update)
两侧都加空格 算术+ - * / % 移位<< >> 位& | ^ 赋值= += -= *= /= %= <<= >>= &= |= ^= 关系== != < > <= >= 逻辑&& || 条件? :
后面不加空格 关键字sizeof typedef aligof __attribute__ defined 一元操作符+ - ++ -- ! (int) 求反~ 取址或引用& 取值*
结构体成员访问符. -> 数值下标a[5]
5 长的行和长的字符串要分行写
6 函数内部变量申请要在函数前部分申请
7 C所有注释用/*..*/格式,C++单行注释用//格式,多行注释用/*..*/,都要在语句或文件的前面或右边
8 尽量避免使用全局变量;对于多次使用的常量,用宏或者枚举代替
9 减少函数本身或函数间的递归调用;函数的参数1-3个;函数体不能太长,一个函数完成一个功能;检查函数输入参数的有效性
10 多重循环将多次循环放在内层,减少CPU切入循环层的次数;多次循环体内要避免含判断语句,将循环语句置于判断语句的代码块内。
11 检查是否存在野指针、内存泄露、引用未初始化变量、数组越界,是否有异常处理等
12 BOOL类型变量直接跟1、0、TRUE、FALSE比较是不良习惯 良好习惯:if (flag)或者if (!flag) 不良习惯:if (flag == 1/TRUE)
13 float变量与零值比较,良好习惯const float EPSINON = 0.00001; if ((x >= - EPSINON) && (x <= EPSINON)),不用== !=用>= <=
14 if判断时候 良好习惯:if (1 == a) 不良习惯:if(a == 1)
15 使用半开半闭的for循环变量 良好习惯:for (int x = 0; x < N; x++) 不良习惯:for (int x = 0; x <= N - 1; x++)
16 C++中const常量完全代替宏常量,C中用#define宏常量; 将对外公开的常量放在头文件中,不对外公开的常量放在定义文件中头部
17 使用断言assert assert(真);表示后面的语句能执行,在函数的入口处要使用断言检测参数的有效性
18 数组、指针、引用在声明的时候一定要赋初值
19 函数中不要return指向“栈内存“的指针或引用
20 用malloc/new申请内存后,要立即检查指针值是否为NULL防止使用指针值为NULL的内存;free/delete释放内存后,要将指针设置为 NULL防止产生野指针;指针消亡后并不表示它所指的内存会被自动释放,内存被释放了并不表示指向它的指针会消亡或成为NULL指针
21 函数的参数缺省值只能出现在函数的声明中,而不能出现在定义体中。有多个参数,参数只能从后向前缺省void Foo(int x, int y=0, int z=0);
22 inline关键字必须在函数定义体前面才有效,在声明体前面不起作用,所以良好的风格是在定义体前加inline而声明体不加
23 类的数据成员的初始化可以采用初始化表或函数体内赋值两种方式,非内部数据类型的成员对象应当采用初始化表以提高效率
24 任何不会修改数据成员的函数都应该声明为 const 类型。基类与派生类的析构函数应该为虚,即加virtual。
25 赋值函数一般分四个步骤: (1)检查自赋值;(2)释放原有内存资源;(3)分配新的内存资源,并复制内容;(4)返回 *this。
头文件模范:不提倡使用全局变量
****************************************************************
/*
* Copyright (c) 2001, 上海贝尔有限公司网络应用事业部
* All rights reserved.
*
* 文件名称: filename.h
* 文件标识: 见配置管理计划书
* 摘 要: 简要描述本文件的内容
*
* 当前版本: 1.1
* 作 者: 输入作者(或修改者)名字
* 完成日期: 2001年7月20日
*
* 取代版本: 1.0
* 原作者 : 输入原作者(或修改者)名字
* 完成日期: 2001年5月10日
*/
#ifndef GRAPHICS_H // 防止 graphics.h 被重复引用
#define GRAPHICS_H
#include <math.h> // 引用标准库的头文件
…
#include “myheader.h” // 引用非标准库的头文件
…
void Function1(…); // 全局函数声明
…
class Box // 类结构声明
{
…
};
#endif
****************************************************************
定义文件模范
****************************************************************
/*
* Copyright (c) 2001, 上海贝尔有限公司网络应用事业部
* All rights reserved.
*
* 文件名称: filename.h
* 文件标识: 见配置管理计划书
* 摘 要: 简要描述本文件的内容
*
* 当前版本: 1.1
* 作 者: 输入作者(或修改者)名字
* 完成日期: 2001年7月20日
*
* 取代版本: 1.0
* 原作者 : 输入原作者(或修改者)名字
* 完成日期: 2001年5月10日
*/
#include “graphics.h” // 引用头文件
…
// 全局函数的实现体
void Function1(…)
{
…
}
// 类成员函数的实现体
void Box::Draw(…)
{
…
}
****************************************************************
Windows下开发命名规则
****************************************************************
宏或者常量用大写加下划线 #define MAX_LENGTH 10; const int MAX_LENGTH = 10;
函数名或者类名用首字母大写的驼峰法 void SetValue(); class Student{};
变量名用首字母小写的驼峰法 int drawMode;
静态变量要加s_ static int s_initValue;
全局变量要加g_ int g_howManyMoney;
类的成员变量加m_ 如m_initWidth;
****************************************************************
Linux下开发命名规则
****************************************************************
宏或者常量用所有大写 #define MAXLENGTH 10; const int MAXLENGTH = 10;
函数名或者类名用 do_something
变量名用 do_something
****************************************************************
使用指针形参申请内存
****************************************************************
void GetMemory(char *p, int num)//用指针申请动态内存是不可行的
{
p = (char *)malloc(sizeof(char) * num);//传递的是实际指针的副本,如调用时指针str的副本_str申请新内存,而str不申请
}
void Test(void)
{
char *str = NULL;
GetMemory(str, 100); //str 仍然为 NULL,每调用一次GetMemory函数,内存泄露一次
strcpy(str, "hello"); //运行错误
}
void GetMemory2(char **p, int num)//用指向指针的指针申请动态内存是可行的
{
*p = (char *)malloc(sizeof(char) * num);
}
void Test2(void)
{
char *str = NULL;
GetMemory2(&str, 100); // 注意参数是 &str,而不是 str
strcpy(str, "hello");
cout<< str << endl;
free(str);
}
char *GetMemory3(int num)//用函数返回指针类型值来申请动态内存是可行的
{
char *p = (char *)malloc(sizeof(char) * num); //必须使用堆内存,才能在执行完后不释放
/* char p[] = "hello world"; 这种方式使用栈内存,p为NULL,不可行 */
/* char *p = "hello world"; 这种方式使用静态存储区,p指向一个只读内存块*/
return p;
}
void Test3(void)
{
char *str = NULL;
str = GetMemory3(100);
strcpy(str, "hello");
cout<< str << endl;
free(str);
}
****************************************************************
野指针:指向错误内存数据的指针 NULL指针:不指向任何内存的指针
****************************************************************
class A
{
public:
void Func(void){ cout << “Func of class A” << endl; }
};
void Test(void)
{
A *p;
{
A a;
p = &a;
}// 注意 a 的生命期
}
p->Func(); // p 是“野指针”,因为a在花括号后已经被释放,p指向的是错误的内存数据
}
****************************************************************
malloc/free与new/delete的区别
****************************************************************
/*malloc/free不能执行构造函数和析构函数,要调用别的函数来完成初始化和清除的工作
**new/delete包含了对象的初始化和清除工作,针对内部数据类型这两者没区别
**针对自定义的类类型,应该使用new/delete,能够自动实现初始化和清除工作*/
class Obj
{
public :
Obj(void){ cout << “Initialization” << endl; }
~Obj(void){ cout << “Destroy” << endl; }
void Initialize(void){ cout << “Initialization” << endl; }
void Destroy(void){ cout << “Destroy” << endl; }
};
void UseMallocFree(void)
{
Obj *a = (obj *)malloc(sizeof(obj)); // 申请动态内存
a->Initialize(); // 初始化
//…
a->Destroy(); //清除工作
free(a); //释放内存
}
void UseNewDelete(void)
{
Obj *a = new Obj; // 申请动态内存并初始化
//…
delete a; // 清除并释放内存
}
****************************************************************
成员函数的重载、覆盖和隐藏
****************************************************************
成员函数被重载的特征:
(1)相同的范围(在同一个类中);
(2)函数名字相同;
(3)参数不同;
(4)virtual关键字可有可无。
覆盖是指派生类函数覆盖基类函数,特征是:
(1)不同的范围(分别位于派生类与基类);
(2)函数名字相同;
(3)参数相同;
(4)基类函数必须有virtual关键字。
隐藏是指派生类的函数屏蔽了与其同名的基类函数,特征是:
(1)如果派生类的函数与基类的函数同名,但是参数不同。此时,不论有无virtual
关键字,基类的函数将被隐藏(注意别与重载混淆)。
(2)如果派生类的函数与基类的函数同名,并且参数也相同,但是基类函数没有virtual
关键字。此时,基类的函数被隐藏(注意别与覆盖混淆)。
****************************************************************
inline函数
****************************************************************
inline void Foo(int x, int y); // inline仅与函数声明放在一起,不是真的inline函数
void Foo(int x, int y)
{
…
}
void Foo(int x, int y);
inline void Foo(int x, int y) // inline与函数定义体放在一起,是真的inline函数
{
…
}
class A
{
public:
void Foo(int x, int y) { … }// 定义在类声明之中的成员函数将自动地成为inline函数,但不是良好的风格
}
// 头文件
class A
{
public:
void Foo(int x, int y);
}
// 定义文件
inline void A::Foo(int x, int y) //良好的风格
{
…
}
****************************************************************