http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#The__define_Guard
Gist:
- 头文件:
- #define: <PROJECT>_<PATH>_<FILE>_H_.
- #include: 当forward declaration(for example: class A;) 够用时别再用#include了
- 在没有类定义的情况下(For example, only declare class Foo), 依然可用的有:
- 数据成员是Foo* or Foo&
- 函数的参数是Foo
- static数据成员是Foo
- 在没有类定义的情况下(For example, only declare class Foo), 依然可用的有:
- inline:
- 不要inline 超过10行代码的函数
- 尽量不要inline析构函数,因为析构函数会对父类的析构函数有潜在的调用
- 不要inline有循环或者switch的函数
- vitural, recursive函数一般不会被编译器认可为inline.
- inline file
- file name with -inl.h suffix
- inline函数要定义在头文件里,简单的直接放在.h里,复杂的放在-inl.h里
- -inl.h 同样放置模板函数的定义
- 函数参数顺序
- input -> output
- input: const reference. output/input: non-const pointers
- include头文件的顺序
- preferred files(with our main purpose), C library, C++ library, other libraries'
.h, your project's.h 在上面满足的情况下,按字母排
- preferred files(with our main purpose), C library, C++ library, other libraries'
Scoping
Namespace匿名的namespace是鼓励的。 但是小心不注意违反了C++ ODR原则。在.h里别用匿名的namespacenamed namespace wrap在 include, 全局的定义和申明, 其他namespace 的forward的class声明之后不能用using-directive把整个namespace包含进来, 但包含specific的方法,class是允许的,namespace alias也是允许的(但是要避免在公共的头文件里用)。
Nested Classnested class 只能在包含它的类里forward-declared, 其他要使用nested class只能inlcude整个头文件定义尽量不要把nest class public, 除非是接口的一部分
全局函数,static member, nonmember函数尽量不要定义全局函数,而是放到匿名namespace或者static-linkage里来限制范围
本地变量在声明的时候初始化为了节省消耗,在loop外定义变量声明离使用越近越好
静态以及全局变量由于静态,全局变量初始化的不确定性,不允许静态或者全局变量是非POD类型即使是POD对象,初始化不能依赖于可能发生初始化不确定性的函数实在需要非POD的话,可以申明为指针,并且在初始化确定的函数中初始化(main or pthread_once)
Classes
构造函数构造函数应该只放置成员变量的初始化,复杂的其他操作放到额外的init方法里。禁止在构造函数使用exception特性禁止在构造函数里使用virtual 函数,因为这里virtual函数不会dispatch构造函数里不要访问潜在的全局变量always至少创建无参数的构造函数,不要交给compiler来做为了防止implict conversion, 在只有一个参数的构造函数前加explict, 如果有例外要用comments说明
拷贝构造函数可以避免使用拷贝构造函数,比如改用pointer, reference在stl container中或者函数参数中不需要copyable的时候,把拷贝构造函数和赋值函数都要显式禁止了如果需要copyable, 尽量另外定义拷贝函数而不是使用拷贝构造函数,eg CopyFrom
Struct vs. Class只有当纯数据集合的时候才用struct, 并且struct里的函数只能和数据提取/设置有关, 其他的用class
继承分为实现继承和接口继承继承要public inheritance对于实现继承,组合会是更好的选择对于子类的析构函数要为virtual, 如果class有virtual的函数禁止protected member function/variable重新实现virtual 函数,必须在前面同样加上virtual
多重继承多重继承只能用在一个是真正父类, 其他都是接口;或者全是接口类的情况下
接口类suffix with Interface只有纯虚函数或者static成员函数没有非static成员变量只能有protected的无参数构造函数
访问控制除了static const成员变量外,其他的都为private,并且提供set/get函数去访问命名规则:var: a_; getter: a(); setter: set_a()setter/getter一般inline在.h里
类成员声明顺序public -> protected -> private- Typedefs and Enums
- Constants (
static constdata members) - Constructors
- Destructor
- Methods, including static methods
- Data Members (except
static constdata members)
- 操作符重载
- 尽量不要重载操作符, 如果实在要做,comment他
- 不要重载&, 因为如果重载了会导致forward declare可能不安全
Others
参数input: value/const reference/const pointerouput: pointer不允许non-const reference
重载函数尽量用make sense 的函数名来代替重载函数, 让读者不看参数也能知道调用的是什么函数
函数参数默认值为了防止copy-paste的时候发现旧的code在新的code里不适合,但是因为有默认值看不出来的情况,不要使用函数参数默认值,除非为了模仿可变长参数
友元可以使用友元,在设计unittest的时候可以把unittest class作为 tested class的友元类
异常不使用异常。。。。异常安全代码的编写, 异常安全是指发生异常的时候会rollback回异常前的初始状态,所以不会对系统有影响http://www.newasp.net/tech/program/20148.html
RTTI不使用RTTI, 可能就改用double-dispatch solution, 像 visitor design
Casting不要使用c-style casting, 像int x = (int)y;用const_cast 去掉const用static_cast代替c-sytle cast来转换值类型, 或者显式的把pionter转对除了在unit code里,其他地方不要使用dynamic_cast用reinterpret_cast去进行指针之间或者指针和int之间的不安全的转换
Stream别使用stream, 用printf +read/write代替
Preincrement and Predecrement用Preincrement and Predecrement代替post-, 如果效果一样的情况下
Const尽量使用const, 在成员函数,变量中任何不变的地方都用const
Int注意int和uint用stdint里的int32_t等来明确指定长度,当需要的时候
64位兼容性当要算指针的时候,用intptr_t代替sizeof(void*) != sizeof(int)注意strcuture alignment
Macro尽量不用##生成名称不要再.h里定义macro
0和NULL对应int用0, 指针用NULL,char用‘/0'
sizeof用sizeof(varname)代替sizeof(type), 因为var很可能会换type, 如果用type就太死板了
本文详细介绍了C++编程中应遵循的各项规范,包括头文件保护、包含顺序、命名约定、类和结构体的设计、构造函数及析构函数的使用、继承方式的选择等。还特别强调了避免使用异常和RTTI的重要性。
1万+

被折叠的 条评论
为什么被折叠?



