AIGC标识 基于“Google C++ Style Guide”的,由AI总结的一套编码规范(自用)

Google C++ 编码规范总结(学生作业实用版)

适用场景:大学 C++ 编程作业、课程设计、小型个人项目
参考来源:Google C++ Style Guide
目标:写出别人愿意读、自己回头能看懂的 C++ 代码。若老师有指定风格,以老师要求优先。

0. 一页速查表

项目 规则 示例
文件名 全小写 + 下划线 student_record.h
类型名 大驼峰 StudentRecord
变量名 小写 + 下划线 student_name
类成员变量 小写 + 下划线 + 结尾下划线 student_name_
常量名 k + 大驼峰 kMaxSize
函数名 大驼峰 CalculateGpa()
命名空间 小写 + 下划线 my_project
全大写 + 下划线 MAX_BUFFER_SIZE
枚举值 k + 大驼峰 kColorRed
缩进 2 个空格 不用 Tab
行宽 不超过 80 字符 超长要换行
头文件保护 #ifndef / #define / #endif PROJECT_PATH_FILE_H_
类型转换 用 C++ 风格 static_cast<int>(x)
空指针 nullptr int* p = nullptr;
只读引用 const const std::string& name

1. 核心原则

Google C++ Style Guide 的目标不是限制写法,而是管理 C++ 的复杂性。写作业时记住三点:

  1. 读者优先:代码被阅读的时间远多于被编写的时间,可读性比“写得快”更重要。
  2. 保持一致:统一命名、缩进、注释风格,让读者能快速抓住结构。
  3. 规则服务于可读性:不要为了炫技使用复杂特性,简单直接通常更好。

2. 命名规范

2.1 通用原则

  • 命名要有描述性,少用缩写。
  • 不要吝啬变量名长度,student_namesn 好。
  • 团队/作业中保持一致,不要同一份代码混用多种风格。

2.2 各类命名规则

类型 规则 示例
文件名 全小写,下划线分隔 my_useful_class.cchttp_server_logs.h
类型名 大驼峰 UrlTableStudentRecord
普通变量 小写,下划线分隔 table_namenum_students
类数据成员 小写 + 下划线 + 结尾下划线 student_name_grades_
常量 k + 大驼峰 kDaysInAWeekkMaxBufferSize
函数名 大驼峰 AddGrade()CalculateGpa()
命名空间 全小写,下划线分隔 my_project
枚举值 k + 大驼峰 kColorRedkStatusOk
全大写,下划线分隔 MAX_BUFFER_SIZE

注意:Google 风格中,常量名通常是 k 开头的大驼峰,而不是全大写。全大写一般留给宏。

2.3 示例代码


// 类名用大驼峰
class StudentRecord {
 public:
  // 普通函数名用大驼峰
  void AddGrade(double grade);
  double CalculateGpa() const;

  // 简单存取器可像变量一样命名
  const std::string& student_name() const { return student_name_; }
  void set_student_name(const std::string& name) { student_name_ = name; }

 private:
  // 成员变量小写 + 结尾下划线
  std::string student_name_;
  std::vector<double> grades_;
};

void StudentRecord::AddGrade(double grade) {
  if (grade >= 0.0 && grade <= 4.0) {
    grades_.push_back(grade);
  }
}

3. 文件与头文件

3.1 头文件保护

所有头文件都应使用 #ifndef / #define / #endif 保护,防止多重包含。命名格式:

#ifndef PROJECT_PATH_FILE_H_
#define PROJECT_PATH_FILE_H_

// ... 声明内容 ...

#endif  // PROJECT_PATH_FILE_H_
例如 foo/bar/baz.h:

#ifndef FOO_BAR_BAZ_H_
#define FOO_BAR_BAZ_H_

// ...

#endif  // FOO_BAR_BAZ_H_

3.2 #include 顺序

按以下顺序包含头文件,每组之间空一行:

// 1. 相关头文件(本 .cc 文件对应的 .h)
#include "foo/server/fooserver.h"

// 2. C 系统头文件
#include <unistd.h>

// 3. C++ 标准库头文件
#include <string>
#include <vector>

// 4. 其他库的头文件
#include "third_party/absl/flags/flag.h"

// 5. 本项目内的头文件
#include "base/basictypes.h"

3.3 前置声明

Google 风格目前建议:尽量避免前置声明,优先 #include 需要的头文件。前置声明虽然能减少编译依赖,但容易引发维护问题和未定义行为。写作业时直接包含头文件更省心。

3.4 内联函数

内联函数只建议用于短小函数,通常不超过 10 行。复杂函数不要强行内联。

4. 作用域与命名空间

4.1 使用命名空间

除少数特殊情况外,代码应放在命名空间中,避免全局命名冲突:

namespace my_project {
namespace foo {

class Bar {
  // ...
};

}  // namespace foo
}  // namespace my_project

注意:命名空间内容通常不额外缩进。

4.2 禁止 using namespace

不要使用 using namespace std; 也不要使用 using namespace foo;。这会把大量名字引入当前作用域,容易冲突。

4.3 匿名命名空间

如果某个函数或变量只在本文件内使用,可放入匿名命名空间:

namespace {

int HelperFunction() {
  return 42;
}

}  // namespace

5. 类规范

5.1 struct 与 class

仅当只有数据成员、没有方法时使用 struct。其他情况一律使用 class。

struct Point {
  double x;
  double y;
};

class StudentRecord {
 public:
  void AddGrade(double grade);
 private:
  std::string student_name_;
  std::vector<double> grades_;
};

5.2 显式构造函数

单参数构造函数应使用 explicit,防止隐式类型转换:

class Foo {
 public:
  explicit Foo(int x);
};

5.3 访问控制与声明顺序

类中成员声明顺序建议:public: -> protected: -> private:。不要把 protected 和 private 的方法、变量混在一起。

5.4 继承

优先使用组合,而不是继承。如果必须继承,确保基类有合适的析构函数(多态基类用 public virtual 析构,非多态基类用 protected 非虚析构)。

6. 函数规范

6.1 函数应当简短

函数最好短小凝练,一个函数只做一件事。过长函数应拆分为多个小函数。

6.2 参数顺序

参数顺序:输入参数在前,输出参数在后。

void ProcessInput(const std::string& input, std::string* output);

6.3 引用参数

所有按引用传递的参数必须加 const,除非函数需要修改该参数:

void PrintName(const std::string& name);  // 好的做法

6.4 返回值

倾向于按值返回。如果返回已有对象,可按引用返回。避免返回指针,除非它可能为空。

7. 常用 C++ 特性建议

7.1 const 与 constexpr

在任何可能的情况下使用 const。编译期常量优先使用 constexpr。

const int kMaxSize = 100;
constexpr double kPi = 3.1415926;

7.2 类型转换

使用 C++ 风格类型转换,不要使用 C 风格转换:

// 好的做法
int y = static_cast<int>(x);

// 不好的做法
int y = (int)x;

7.3 智能指针

优先使用 std::unique_ptr 表示独占所有权。需要共享所有权时使用 std::shared_ptr。避免手动 new / delete。

auto student = std::make_unique<StudentRecord>();

7.4 auto

类型明显时可以使用 auto,但不要滥用。如果类型不明显,写清楚类型更好。

auto it = students.begin();  // 可以
auto count = students.size();  // 可以

7.5 Lambda 表达式

适当使用 lambda。不要使用默认捕获:

// 不好的做法
auto f = [=]() { return x + y; };

// 好的做法
auto f = [x, y]() { return x + y; };

7.6 整数类型

涉及跨平台或明确大小时,使用

&#35;include <cstdint>

int32_t a = 10;
int64_t b = 10000000000LL;

7.7 nullptr

用 nullptr 表示空指针,不要用 NULL 或 0:

int* p = nullptr;

7.8 预处理宏

避免使用宏定义常量或函数,优先使用 const、constexpr、enum class、内联函数。宏只保留给必要的条件编译等场景。

8. 注释规范

8.1 文件注释

每个文件开头应有文件注释。作业中可以写课程、姓名、学号、文件功能:

// 文件名:student_record.cc
// 作者:张三
// 学号:2024xxxxxx
// 功能:实现 StudentRecord 类的相关方法。

8.2 函数注释

函数声明前应说明功能、参数、返回值:

// 计算学生的加权平均分。
// 参数 weighted_scores: 键为课程名,值为 (分数, 权重) 的 pair。
// 返回: 加权平均分,范围 [0.0, 4.0]。
double CalculateWeightedGpa(
    const std::map<std::string, std::pair<double, double>>& weighted_scores);

8.3 实现注释

在代码中解释“为什么”,而不是“是什么”。不明显的逻辑要写注释。

8.4 TODO 注释

格式:// TODO(username): 处理输入为空的情况。

9. 格式规范

9.1 基本格式

缩进使用 2 个空格,只用空格不用 Tab。每行不超过 80 个字符。尽量使用 ASCII,非 ASCII 用 UTF-8。函数体左大括号不换行;控制语句左大括号不换行。

9.2 条件语句

if (condition) {
  // 2 空格缩进
} else if (other_condition) {
  // ...
} else {
  // ...
}

9.3 指针和引用

  • 和 & 紧跟在类型后面,与变量名之间加空格:
int* ptr;
const std::string& name = GetName();

9.4 布尔表达式

逻辑运算符放在行尾:

if (this_one_thing > this_other_thing &&
    a_third_thing == a_fourth_thing &&
    yet_another && last_one) {
  // ...
}

9.5 循环

for (int i = 0; i < n; ++i) {
  // ...
}

for (const auto& student : students) {
  // ...
}

10. 作业提交前检查清单

□ 文件名全小写,用下划线分隔。
□ 类型名用大驼峰,变量名用小写加下划线。
□ 类成员变量以 _ 结尾。
□ 常量名用 k 开头的大驼峰。
□ 函数名用大驼峰。
□ 头文件有 #ifndef / #define / #endif 保护。
#include 按顺序分组。
□ 没有 using namespace std;。
□ 单参数构造函数用了 explicit
□ 只读引用参数加了 const
□ 类型转换使用 static_cast<>() 等 C++ 风格。
□ 空指针使用 nullptr
□ 缩进 2 个空格,每行不超过 80 字符。
□ 关键函数有注释,复杂逻辑有说明。
□ 编译无警告,尽量使用 -Wall -Wextra。
□ 如果老师有指定风格,优先遵循老师要求。

11. 参考资料

Google C++ Style Guide 英文原版

Google 开源项目风格指南中文版

cpplint 代码检查工具

posted @ 2026-09-22 19:24  ham30747  阅读(15)  评论(1)    收藏  举报