use*_*999 6 c++ design-guidelines
前言
Google风格指南包含前瞻性声明的缺点列表
前向声明可以隐藏依赖项,允许用户代码在标题更改时跳过必要的重新编译.
随后对库的更改可能会破坏前向声明.函数和模板的前向声明可以防止标题所有者对其API进行其他兼容的更改,例如扩展参数类型,添加具有默认值的模板参数或迁移到新的命名空间.
从名称空间std ::转发声明符号会产生未定义的行为.
可能很难确定是否需要前向声明或完整#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*).
从标题中声明多个符号的前向可能比简单地#include the header更加冗长.
构造代码以启用前向声明(例如,使用指针成员而不是对象成员)可以使代码更慢,更复杂.
题
我特别感兴趣的是第一点,因为我无法想出一个单一的场景,当标题改变时,前向解除将跳过必要的重新编译.谁能告诉我这是怎么发生的?或者这是谷歌代码库固有的东西?
由于这是列表中的第一点,因此它似乎也很重要.
\n\n\n我无法想出一个场景,即当标头更改时,前向声明将跳过必要的重新编译。
\n
我认为这也有点不清楚,也许可以说得更清楚一些。
\n\n隐藏依赖项意味着什么?
\n\n让\xe2\x80\x99s 表示您的文件main.cc需要header.h正确构建。
如果main.cc包含header.h,则这是直接依赖项。
如果main.cc先包含lib.h,然后lib.h包含header.h,则这是间接依赖。
如果main.cc以某种方式依赖lib.h但不包含的话不会生成构建错误lib.h,那么我可以将其称为隐藏依赖项。
然而,我不认为“隐藏”这个词是一个常见术语,所以我同意可以对措辞进行细化或扩展。
\n\n我有main.c,,lib.h和types.h。
这是main.c:
#include "lib.h"\nvoid test(D* x) { f(x); }\nRun Code Online (Sandbox Code Playgroud)\n\n这是lib.h:
#include "types.h"\nvoid f(B*);\nvoid f(void*);\nRun Code Online (Sandbox Code Playgroud)\n\n这是types.h:
struct B {};\nstruct D : B {};\nRun Code Online (Sandbox Code Playgroud)\n\n现在,要生成正确的代码main.cc取决于。types.h然而,main.cc仅对 具有直接依赖关系lib.h,它对 具有隐藏依赖关系types.h。如果我在 中使用前向声明lib.h,那么就会中断main.cc。但仍然main.cc可以编译!
中断的原因main.cc是因为它不包含types.h,即使main.cc取决于中的声明types.h。前向声明使这成为可能。