【C/C++】Google 出品的代码规范(Google C++ Style Guide)

文章目录

  • I. 开篇, 一图胜千言
  • II. 分门别类, 娓娓道来
    • Principles 原则
    • Header Files 头文件
      • Self-contained Headers
      • The #define Guard #define 保护
      • Forward Declarations 前置声明
      • Inline Functions 内联函数
      • Names and Order of Includes
    • Scope 域
      • Namespaces 命名空间
      • Nonmember, Static Member, and Global Functions
      • Local Variables
      • Static and Global Variables
    • Classes 类
      • Doing Work in Constructors
      • Implicit Conversions
      • Copyable and Movable Types
      • Structs vs. Classes
      • Inheritance
      • Operator Overloading
      • Access Control
      • Declaration Order
    • Functions 函数
      • Output Parameters
      • Write Short Functions
      • Reference Arguments
      • Function Overloading
      • Default Arguments
      • Trailing Return Type Syntax
    • Google-Specific Magic
      • Ownership and Smart Pointers
      • cpplint
    • Other C++ Features
      • Rvalue References
      • Friends
      • Exceptions
      • noexcept
      • Run-Time Type Information(RTTI)
      • Casting
      • Streams
      • Preincrement and Predecrement
      • Use of const
      • Use of constexpr
      • Integer Types
      • 64-bit Portabaility
      • Preprocessor Macros
      • 0 and nullptr/NULL
      • sizeof
      • auto
      • Braced Initializer List
      • Lambda Expressions
      • Template metaprogramming
      • Boost
      • std::hash
      • C++ 11
      • Nonstandard Extensions
      • Aliases
    • Naming 命名
      • 命名风格
      • 一般规则
      • File Names
      • Type Names
      • Variable Names
      • Class Data Members
      • Struct Data Members
      • Function Names
      • Namespace Names
      • Macro Names
      • Enumerator Names
      • Exceptions to Naming Rules
    • Comments 注释
      • 注释风格
      • 文件注释
      • 类注释
      • 函数注释
        • 函数声明 declaration
        • 函数实现 implementation
        • 函数体 body
        • 函数参数 parameters
      • TODO 注释
    • Formatting
      • Line Length
      • Non-ASCII Characters
      • Spaces vs. Tabs
      • Function Declarations and Definitions
      • Lambda Expressions
      • Function Calls
      • Braced Initializer List Format
      • Conditionals
      • Loops and Switch Statements
      • Pointer and Reference Expresions
      • Boolean Expressions
      • Return Values
      • Variable and Array Initialization
      • Preprocessor Directives
      • Class Format
      • Constructor Initializer Lists
      • Namespace Formatting
      • Horizontal Whitespace
      • Vertical Whitespace
    • Exceptions to the Rules
      • Existing Non-conformant Code
      • Windows Code
    • Parting Words : Use common sense and BE CONSISTENT
  • III. 专题深入, 积沙成塔
  • Ref

I. 开篇, 一图胜千言

x

此图来自 一张图总结Google C++编程规范(Google C++ Style Guide)

具体细节,娓娓道来。

II. 分门别类, 娓娓道来

本章来自于官方文档的摘录. Google C++ Style Guide

Principles 原则

  • Style rules should pull their weight.
  • Optimize for the reader, not the writer
  • Be consistent with existing code
  • Be consistent with the broader C++ community when appropriate
  • Avoid surprising or dangerous constructs
  • Avoid constructs that our average C++ programmer would find tricky or hard to maintain
  • Be mindful of our scale
  • Concede to optimization when necessary

Header Files 头文件

Self-contained Headers

Header files should be self-contained (compile on their own) and end in .h. Non-header files that are meant for inclusion should end in .inc and be used sparingly.

The #define Guard #define 保护

  • 按文件夹顺序: ___H_.

. For example, the file foo/src/bar/baz.h in project foo should have the following guard:

#ifndef FOO_BAR_BAZ_H_
#define FOO_BAR_BAZ_H_

...

#endif  // FOO_BAR_BAZ_H_

Forward Declarations 前置声明

A “forward declaration” is a declaration of a class, function, or template without an associated definition.

  • 尽量不用, 需要什么就 #include

Inline Functions 内联函数

  • 小于 10 行的简单直接的小程序, 才写成内联函数

Names and Order of Includes

In dir/foo.cc or dir/foo_test.cc, whose main purpose is to implement or test the stuff in dir2/foo2.h, order your includes as follows:

  1. dir2/foo2.h.
  2. A blank line
  3. C system files.
  4. C++ system files.
  5. A blank line
  6. Other libraries’ .h files.
  7. Your project’s .h files.

For example, the includes in google-awesome-project/src/foo/internal/fooserver.cc might look like this:

#include "foo/server/fooserver.h"

#include 
#include 
#include 

#include "base/basictypes.h"
#include "base/commandlineflags.h"
#include "foo/server/bar.h"
  • system-specific code needs conditional includes. 后置
#include "foo/public/fooserver.h"

#include "base/port.h"  // For LANG_CXX11.

#ifdef LANG_CXX11
#include 
#endif  // LANG_CXX11

Scope 域

Namespaces 命名空间

  • 所有逻辑代码一律放在 namespace 里
// In the .h file
namespace mynamespace {

// All declarations are within the namespace scope.
// Notice the lack of indentation.
class MyClass {
 public:
  ...
  void Foo();
};

}  // namespace mynamespace
// In the .cc file
namespace mynamespace {

// Definition of functions is within scope of the namespace.
void MyClass::Foo() {
  ...
}

}  // namespace mynamespace
  • 一律禁止使用 using namespace XXX, 如 using namespace std
  • 可以使用 using, 如 using std::string
  • 不使用 inline namespace.

Nonmember, Static Member, and Global Functions

  • 放在单独的 namespace 中

Local Variables

  • Place a function’s variables in the narrowest scope possible, and initialize variables in the declaration.
int i;
i = f();      // Bad -- initialization separate from declaration.
int j = g();  // Good -- declaration has initialization.


std::vector<int> v;
v.push_back(1);  // Prefer initializing using brace initialization.
v.push_back(2);
std::vector<int> v = {
   1, 2};  // Good -- v starts initialized.


//Variables needed for if, while and for statements should normally be declared within those statements, 
// so that such variables are confined to those scopes. E.g.:

while (const char* p = strchr(str, '/')) str = p + 1;

// There is one caveat: if the variable is an object, its constructor is invoked every time 
// it enters scope and is created, and its destructor is invoked every time it goes out of scope.

// Inefficient implementation:
for (int i = 0; i < 1000000; ++i) {
   
  Foo f;  // My ctor and dtor get called 1000000 times each.
  f.DoSomething(i);
}
// It may be more efficient to declare such a variable used in a loop outside that loop:

Foo f;  // My ctor and dtor get called once each.
for (int i = 0; i < 1000000; ++i) {
   
  f.DoSomething(i);
}

Static and Global Variables

Classes 类

Doing Work in Constructors

  • 绝不能调用虚函数 Avoid virtual method calls in constructors
  • 决不能调用可能失败的操作 avoid initialization that can fail if you can’t signal an error.
  • 可以把上面的操作添加到一个 Init() 函数中, 注意 Init 不要滥用
  • 推荐使用 factory function, 具体理由参见 TotW #42 类似这样
// foo.h
class Foo {
   
 public:
  // Factory method: creates and returns a Foo.
  // May return null on failure.
  static std::unique_ptr<Foo> Create();

  // Foo is not copyable.
  Foo(const Foo&) = delete;
  Foo& operator=(const Foo&) = delete;

 private:
  // Clients can't invoke the constructor directly.
  Foo();
};

// foo.c
std::unique_ptr<Foo> Foo::Create() {
   
  // Note that since Foo's constructor is private, we have to use new.
  return absl::WrapUnique(new Foo());
}

Implicit Conversions

  • 单参数构造函数必须使用 explicit
  • 特例: copy and move constructors should not be explicit since they do not perform type conversion
  • 特例: Implicit conversions can sometimes be necessary and appropriate for types that are designed to transparently wrap other types. In that case, contact your project leads to request a waiver of this rule.
  • Constructors that cannot be called with a single argument may omit explicit.
  • Constructors that take a single std::initializer_list parameter should also omit explicit, in order to support copy-initialization (e.g. MyType m = {1, 2}?.

Copyable and Movable Types

  • A movable type is one that can be initialized and assigned from temporaries.
  • A copyable type is one that can be initialized or assigned from any other object of the same type (so is also movable by definition), with the stipulation that the value of the source does not change.
  • int and string are examples of movable types that are also copyable.
  • std::unique_ptr is an example of a movable but not copyable type (since the value of the source std::unique_ptr must be modified during assignment to the destination)
  • A class’s public API should make explicit whether the class is copyable, move-only, or neither copyable nor movable. Support copying and/or moving if these operations are clear and meaningful for your type.
  • 怎么限制, 以以下的代码形式
class Copyable {
   
 public:
  Copyable(const Copyable& rhs) = default;
  Copyable& operator=(const Copyable& rhs) = default;

  // The implicit move operations are suppressed by the declarations above.
};

class MoveOnly {
   
 public:
  MoveOnly(MoveOnly&& rhs);
  MoveOnly& operator=(MoveOnly&& rhs);

  // The copy operations are implicitly deleted, but you can
  // spell that out explicitly if you want:
  MoveOnly(const MoveOnly&) = delete;
  MoveOnly

你可能感兴趣的:(C/C++,coding,style)