Google风格指南(转发部分)

use*_*999 6 c++ design-guidelines

前言

Google风格指南包含前瞻性声明的缺点列表

  1. 前向声明可以隐藏依赖项,允许用户代码在标题更改时跳过必要的重新编译.

  2. 随后对库的更改可能会破坏前向声明.函数和模板的前向声明可以防止标题所有者对其API进行其他兼容的更改,例如扩展参数类型,添加具有默认值的模板参数或迁移到新的命名空间.

  3. 从名称空间std ::转发声明符号会产生未定义的行为.

  4. 可能很难确定是否需要前向声明或完整#include.用前向声明替换#include可以默默地改变代码的含义:

码:

  // b.h:
  struct B {};
  struct D : B {};

  // good_user.cc:
  #include "b.h"
  void f(B*);
  void f(void*);
  void test(D* x) { f(x); }  // calls f(B*)
Run Code Online (Sandbox Code Playgroud)

如果#include被B和D的forward decls替换,test()将调用f(void*).

  1. 从标题中声明多个符号的前向可能比简单地#include the header更加冗长.

  2. 构造代码以启用前向声明(例如,使用指针成员而不是对象成员)可以使代码更慢,更复杂.

我特别感兴趣的是第一点,因为我无法想出一个单一的场景,当标题改变时,前向解除将跳过必要的重新编译.谁能告诉我这是怎么发生的?或者这是谷歌代码库固有的东西?

由于这是列表中的第一点,因此它似乎也很重要.

Die*_*Epp 2

\n

我无法想出一个场景,即当标头更改时,前向声明将跳过必要的重新编译。

\n
\n\n

我认为这也有点不清楚,也许可以说得更清楚一些。

\n\n

隐藏依赖项意味着什么

\n\n

让\xe2\x80\x99s 表示您的文件main.cc需要header.h正确构建。

\n\n
    \n
  • 如果main.cc包含header.h,则这是直接依赖项。

  • \n
  • 如果main.cc先包含lib.h,然后lib.h包含header.h,则这是间接依赖。

  • \n
  • 如果main.cc以某种方式依赖lib.h但不包含的话不会生成构建错误lib.h,那么我可以将其称为隐藏依赖项。

  • \n
\n\n

然而,我不认为“隐藏”这个词是一个常见术语,所以我同意可以对措辞进行细化或扩展。

\n\n

这是怎么发生的?

\n\n

我有main.c,,lib.htypes.h

\n\n

这是main.c

\n\n
#include "lib.h"\nvoid test(D* x) { f(x); }\n
Run Code Online (Sandbox Code Playgroud)\n\n

这是lib.h

\n\n
#include "types.h"\nvoid f(B*);\nvoid f(void*);\n
Run Code Online (Sandbox Code Playgroud)\n\n

这是types.h

\n\n
struct B {};\nstruct D : B {};\n
Run Code Online (Sandbox Code Playgroud)\n\n

现在,要生成正确的代码main.cc取决于。types.h然而,main.cc仅对 具有直接依赖关系lib.h,它对 具有隐藏依赖关系types.h。如果我在 中使用前向声明lib.h,那么就会中断main.cc。但仍然main.cc可以编译!

\n\n

中断的原因main.cc是因为它不包含types.h,即使main.cc取决于中的声明types.h。前向声明使这成为可能。

\n