前言
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*)
如果将#include替换为B和D的前置声明,test()将调用f(void*)。
从头文件中向前声明多个符号可能比简单地#include头文件更冗长。
构造代码以启用前置声明(例如使用指针成员而不是对象成员)可能会使代码变得更加缓慢且更加复杂。
问题:
我特别关注第一点,因为我想不出任何情况,在这种情况下前置声明会跳过必要的重新编译。有人可以告诉我这怎么会发生吗?还是这是Google代码库固有的问题?
由于这是清单上的第一点,因此似乎非常重要。