Attention: Here be dragons

This is the latest (unstable) version of this documentation, which may document features not available in or compatible with released stable versions of Godot.

C++ 使用规范

依据

从 Godot 4.0 开始,代码库中所使用的 C++ 标准是 C++17 的子集。现代 C++ 带来了许多机会,让我们能够编写更快、更易读的代码,但我们选择将我们对 C++ 的使用限制在一个子集中,原因有这么几点:

  • 易于使用在线编辑器审核代码。这是因为引擎的贡献者在审核代码时并不总是可以使用完整的 IDE。

  • 易于让新手贡献者掌握代码(他们可能不是专业的 C++ 程序员)。Godot 的代码库是公认的易于学习,我们希望继续保持。

To get your pull request merged, it needs to follow the C++ usage guidelines outlined here. Of course, you can use features not allowed here in your own C++ modules or GDExtensions.

备注

在 Godot 4.0 之前的版本中,代码库所使用的 C++ 标准曾是 C++03,外加一些 C++14 扩展。如果你是在为 3.x 分支提交拉取请求而不是 master,就不能使用 C++17 的特性。请确保你的代码能够使用 C++14 编译器构建。

以下规范并不适用于第三方依赖,虽然我们一般倾向于使用小型的库而不是大型的解决方案。另请参阅 引擎贡献者的最佳实践

参见

格式化规范请参阅 代码风格规范

禁用的特性

未在下方列出的特性都是允许的。鼓励尽可能使用 constexpr 变量和 nullptr 等特性。不过请你在使用现代 C++ 特性时保持保守。使用时应当为实际的目的服务,例如提升代码可读性或性能。

标准模板库

我们不允许使用 STL,因为 Godot 提供了自有的数据类型(及其他工具)。详情请参阅 为什么 Godot 不使用 STL(标准模板库)?

This means that pull requests should not use std::string, std::vector and the like. Instead, use Godot's datatypes as described in the 核心类型 documentation.

A 📜 icon denotes the type is part of Variant. This means it can be used as a parameter or return value of a method exposed to the scripting API.

auto 关键字

请勿使用 auto 关键字进行类型推导。虽然可以避免重复,但也可能导致令人费解的代码:

// Not so confusing...
auto button = memnew(Button);

// ...but what about this?
auto result = EditorNode::get_singleton()->get_complex_result();

请记住,拉取请求的审核者一般是没有悬停文档的。大多数情况下,审核者是用 GitHub 的在线查看器审核拉取请求的。

The auto keyword can be used in some special cases, like C++ lambda or Objective-C block definitions and C++ templates. Please ask before using templates with auto in a pull request.

// Full type definitions.
void (*mult64to128)(uint64_t, uint64_t, uint64_t &, uint64_t &) = [](uint64_t u, uint64_t v, uint64_t &h, uint64_t &l) { ... }
void (^JOYSTICK_LEFT)(GCControllerDirectionPad *__strong, float, float) = ^(GCControllerDirectionPad *dpad, float xValue, float yValue) { ... }

// Less clutter with auto.
auto mult64to128 = [](uint64_t u, uint64_t v, uint64_t &h, uint64_t &l) { ... }
auto JOYSTICK_LEFT = ^(GCControllerDirectionPad *dpad, float xValue, float yValue) { ... }

// Compare function for different types.
template <typename T1, typename T2>
constexpr auto MIN(const T1 m_a, const T2 m_b) {
    return m_a < m_b ? m_a : m_b;
}

We chose to forbid auto in all other cases. Thank you for your understanding.

Lambda

应该保守地使用 lambda,需要在能让代码更快或者更简单的同时,不妨碍可读性。请在拉取请求中使用 lambda 前先询问。

#ifdef-based include guards

Starting with 4.5, all files now use the #pragma once directive, as they improve readability and declutter macros. Use of #ifdef-based include guards are now actively discouraged.

try-catch 代码块

禁止使用 trycatch 块进行 C++ 风格的异常处理。这一限制基于多个原因,包括性能、二进制文件大小和代码复杂性。请改用 错误宏

参见

C++ 和 Objective-C 文件中 include 的排序规范请参阅 头文件的引入