Google C++ Convention

    技术2022-05-13  14

    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&函数的参数是Foostatic数据成员是Foo inline: 不要inline 超过10行代码的函数尽量不要inline析构函数,因为析构函数会对父类的析构函数有潜在的调用不要inline有循环或者switch的函数vitural, recursive函数一般不会被编译器认可为inline. inline file file name with -inl.h suffixinline函数要定义在头文件里,简单的直接放在.h里,复杂的放在-inl.h里-inl.h 同样放置模板函数的定义 函数参数顺序 input -> outputinput: 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在上面满足的情况下,按字母排 Scoping Namespace 匿名的namespace是鼓励的。 但是小心不注意违反了C++ ODR原则。在.h里别用匿名的namespacenamed namespace wrap在 include, 全局的定义和申明, 其他namespace 的forward的class声明之后不能用using-directive把整个namespace包含进来, 但包含specific的方法,class是允许的,namespace alias也是允许的(但是要避免在公共的头文件里用)。 Nested Class nested 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 const data members) Constructors Destructor Methods, including static methods Data Members (except static const data 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就太死板了

     

     


    最新回复(0)