问题
Preface
The Google Style Guide includes a list of disadvantages of forward declaration
Forward declarations can hide a dependency, allowing user code to skip necessary recompilation when headers change.
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.
Forward declaring symbols from namespace std:: yields undefined behavior.
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*).
Forward declaring multiple symbols from a header can be more verbose than simply #includeing the header.
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
includesheader.h
, then this is a direct dependency.If
main.cc
includeslib.h
, and thenlib.h
includesheader.h
, then this is an indirect dependency.If
main.cc
somehow depends onlib.h
but does not generate a build error iflib.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 #include
ing 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 #include
ing 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