用户和重构工具不需要为特别场合而包含额外的头文件。
#define保护 #ifndef FOO_BAR_BAZ_H_ #define FOO_BAR_BAZ_H_ ... #endif // FOO_BAR_BAZ_H 尽量避免前置声明waht is 前置声明?
class Date { private: int year, month, day; }; //if want to use this class ,have two ways: //one前置声明 class Date; class Task1 { public: Date getData(); }; //two包含头文件 #include "Date.h" class Task2 { public: Date getData(); }; 慎用内联函数在函数很短,可以内联,但是得保证此函数很少被调用
include的路径和顺序 #include <zylg.h>// find it on system first #include "zylg.h"//find it on project first1.匿名的命名空间会把空间里面的定义的东西自动放在上一级命名空间,比如上述代码可以zylg::s1(),这样保证了全局变量的名称资源(因为具有内部链接性),同时节约了命名空间数量
2.局部变量 将函数变量尽可能至于最小的作用域
3.全局变量和静态变量尽可能在控制范围内,少用
1.不要在构造函数里面调用虚函数,也不要在无法报出错误时进行可能失败的初始化.
2.不要定义隐式类型转换. 对于转换运算符和单参数构造函数, 请使用 explicit 关键字.别让int默默的就double了,explicit可以保证函数不会发生隐式转换,涉及类型转换的应该加上
3.可拷贝类型和可移动类型 如果你的类型需要, 就让它们支持拷贝 / 移动. 否则, 就把隐式产生的拷贝和移动函数禁用.
// MyClass is neither copyable nor movable. MyClass(const MyClass&) = delete; MyClass& operator=(const MyClass&) = delete;4.结构体 仅当只有数据成员时使用 struct, 其它一概使用 class.
继承 使用组合 (YuleFox 注: 这一点也是 GoF 在 <> 里反复强调的) 常常比使用继承更合理. 如果使用继承的话, 定义为 public 继承.
//介绍组合模式 class component { //声明全部你所要用到的函数,在此处为虚函数,不去定义 } class composite:public component { //实现虚函数全部 } class left:public component { //实现个别的虚函数 } /* *在继承的时候,析构函数声明为虚函数,不然会发生内存泄露 */6.多重继承 真正需要用到多重实现继承的情况少之又少. 只在以下情况我们才允许多重继承: 最多只有一个基类是非抽象类; 其它基类都是以 Interface 为后缀的 纯接口类.
7.接口 接口是指满足特定条件的类, 这些类以 Interface 为后缀 (不强制).
8.运算符重载 除少数特定环境外, 不要重载运算符. 也不要创建用户定义字面量.
9.存取控制 将 所有 数据成员声明为 private, 除非是 static const 类型成员 (遵循 常量命名规则). 处于技术上的原因, 在使用 Google Test 时我们允许测试固件类中的数据成员为 protected.
10.声明顺序 类定义一般应以 public: 开始, 后跟 protected:, 最后是 private:. 省略空部分.
1.函数参数顺序 函数的参数顺序为: 输入参数在先, 后跟输出参数.
3.引用参数 所有按引用传递的参数必须加上 const. as:void Foo(const string &in, string *out);
4.函数重载 若要使用函数重载, 则必须能让读者一看调用点就胸有成竹, 而不用花心思猜测调用的重载函数到底是哪一种. 这一规则也适用于构造函数.
5.只允许在非虚函数中使用缺省参数, 且必须保证缺省参数的值始终一致. 缺省参数与 函数重载 遵循同样的规则. 一般情况下建议使用函数重载, 尤其是在缺省函数带来的可读性提升不能弥补下文中所提到的缺点的情况下.
1.所有权与智能指针,动态分配出的对象最好有单一且固定的所有主, 并通过智能指针传递所有权. 所有权是一种登记/管理动态内存和其它资源的技术. 动态分配对象的所有主是一个对象或函数, 后者负责确保当前者无用时就自动销毁前者. 所有权有时可以共享, 此时就由最后一个所有主来负责销毁它. 甚至也可以不用共享, 在代码中直接把所有权传递给其它对象. 智能指针是一个通过重载 * 和 -> 运算符以表现得如指针一样的类. 智能指针类型被用来自动化所有权的登记工作, 来确保执行销毁义务到位. std::unique_ptr 是 C++11 新推出的一种智能指针类型, 用来表示动态分配出的对象的独一无二的所有权; 当 std::unique_ptr 离开作用域时, 对象就会被销毁. std::unique_ptr 不能被复制, 但可以把它移动(move)给新所有主. std::shared_ptr 同样表示动态分配对象的所有权, 但可以被共享, 也可以被复制; 对象的所有权由所有复制者共同拥有, 最后一个复制者被销毁时, 对象也会随着被销毁.
2.cppplint 使用 cpplint.py 检查风格错误.
函数命名, 变量命名, 文件命名要有描述性; 少用缩写.
//文件命名:文件名要全部小写, 可以包含下划线 (_) 或连字符 (-), 依照项目的约定. 如果没有约定, 那么 “_” 更好. //类型名命名:类型名称的每个单词首字母均大写, 不包含下划线 //变量名:变量 (包括函数参数) 和数据成员名一律小写, 单词之间用下划线连接,类变量以下划线结尾 //常量名:声明为 constexpr 或 const 的变量, 或在程序运行期间其值始终保持不变的, 命名时以 “k” 开头, 大小写混合 //函数名;规函数使用大小写混合, 取值和设值函数则要求与变量名匹配 //命名空间:命名空间以小写字母命名. 最高级命名空间的名字取决于项目名称 //枚举;枚举的命名应当和 常量 或 宏 一致: kEnumName 或是 ENUM_NAME.使用 // 或 /* */, 统一就好.
在每一个文件开头加入版权公告.描述了该文件的内容
每个类的定义都要附带一份注释, 描述类的功能和用法, 除非它的功能相当明显.
通常变量名本身足以很好说明变量用途. 某些情况下, 也需要额外的注释说明.
//注:注释别写一些谁看函数都能看出来的废话,不如不写