Google Style Guide (Section Forward Decleration)

家住魔仙堡 提交于 2020-02-14 04:07:26

问题


Preface

The Google Style Guide includes a list of disadvantages of forward declaration

  1. Forward declarations can hide a dependency, allowing user code to skip necessary recompilation when headers change.

  2. A forward declaration may be broken by subsequent changes to the library. Forward declarations of functions and templates can prevent the header owners from making otherwise-compatible changes to their APIs, such as widening a parameter type, adding a template parameter with a default value, or migrating to a new namespace.

  3. Forward declaring symbols from namespace std:: yields undefined behavior.

  4. It can be difficult to determine whether a forward declaration or a full #include is needed. Replacing an #include with a forward declaration can silently change the meaning of code:

Code:

  // 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*)

If the #include was replaced with forward decls for B and D, test() would call f(void*).

  1. Forward declaring multiple symbols from a header can be more verbose than simply #includeing the header.

  2. Structuring code to enable forward declarations (e.g. using pointer members instead of object members) can make the code slower and more complex.

Question

I am particulary interested in the first point, as I cannot come up with a single scenario, where a forward decleration would skip necessary recompilation when headers change. Can anybody tell me how this can happen? Or is this something intrinsic to the google code base?

As this is the first point on the list it also seems rather important.


回答1:


I cannot come up with a single scenario, where a forward declaration would skip necessary recompilation when headers change.

I think this is a bit unclear too, and perhaps could be worded a little more clearly.

What could it mean for a dependency to be hidden?

Let’s say your file main.cc needs header.h in order to be built correctly.

  • If main.cc includes header.h, then this is a direct dependency.

  • If main.cc includes lib.h, and then lib.h includes header.h, then this is an indirect dependency.

  • If main.cc somehow depends on lib.h but does not generate a build error if lib.h is not included, then I might call this a hidden dependency.

I don’t think the word hidden is a commonplace term for this, however, so I agree that the wording could be refined or expanded.

How does this happen?

I have main.c, lib.h, and types.h.

Here is main.c:

#include "lib.h"
void test(D* x) { f(x); }

Here is lib.h:

#include "types.h"
void f(B*);
void f(void*);

Here is types.h:

struct B {};
struct D : B {};

Now, main.cc depends on types.h in order to generate the correct code. However, main.cc only has a direct dependency on lib.h, it has a hidden dependency on types.h. If I use forward declarations in lib.h, then this breaks main.cc. And yet main.cc still compiles!

And the reason that main.cc breaks is because it does not include types.h, even though main.cc depends on the declarations in types.h. Forward declarations make this possible.




回答2:


I am particulary interested in the first point, as I cannot come up with a single scenario, where a forward decleration would skip necessary recompilation when headers change. Can anybody tell me how this can happen?

It will happen because dependency trackers cannot deduce that something in the header file that defines the class changed if you use a forward declaration of the class. However, there is nothing intrinsically wrong about that in most cases.

Or is this something intrinsic to the google code base?

The posted code block about D makes sense. If you don't #include the header that defines D but provide a mere forward declaration, the call to f(x) will resolve to f(void*), which is not what you want.

IMO, avoiding forward declarations in favor of #includeing the header files is a very expensive price to pay to account for just the above use case. However, if you have enough hardware/software resources that the cost of #includeing header files is not a factor, I can see how one could justify such a recommendation.



来源:https://stackoverflow.com/questions/52376111/google-style-guide-section-forward-decleration

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!