Ruf*_*fus 11 c++ forward-declaration google-style-guide
并不是说谷歌风格指南是神圣的圣经,但作为一个新手程序员,它似乎是一个很好的参考.
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更加冗长.
构造代码以启用前向声明(例如,使用指针成员而不是对象成员)可以使代码更慢,更复杂.
然而,对SO的一些搜索似乎表明,前向声明通常是更好的解决方案.
因此,鉴于这些看似非平凡的缺点,有人可以解释这种差异吗?
什么时候忽略部分或全部这些缺点是安全的?
对SO的一些搜索似乎表明,前向声明通常是更好的解决方案.
我不认为这就是SO所说的.你引用的文字是比较"游击队"前方声明,包括正确的包含文件.对于谷歌在这里批评的方法,我认为你不会在SO上找到很多支持.这种糟糕的方法是,"不,不#include包含文件,只需为您想要使用的少数函数和类型编写声明".
正确的包含文件仍然包含它自己的前向声明,并且对SO的搜索将表明这是正确的事情,所以我看到你在哪里认为SO赞成声明.但谷歌并不是说图书馆自己的包含文件不应该包含前向声明,而是说你不应该流氓并为你想要使用的每个函数或类型编写自己的前向声明.
如果你#include是正确的包含文件,并且你的构建链工作,那么依赖关系不会被隐藏,其余的问题大多不适用,尽管包含文件包含声明.仍有一些困难,但这不是谷歌在这里所说的.
特别关注类型的前向声明与它们的类定义相比,(4)给出了一个错误的例子(因为前向声明D不能表示它是从它派生的B,因为你需要类定义).还有一种名为"Pimpl"的技术确实为特定目的小心使用了前向类型声明.因此,你会再次看到对SO的一些支持,但这与支持每个人通常都应该使用前向声明的类而不是#include其头文件的想法不同.
泰特斯·温特斯(Titus Winters)在2014年CppCon演讲中:
我们最近了解到的一个大问题是:向前声明其中带有模板的任何内容都是一个非常糟糕的主意。这导致了您无法相信的维护问题。在某些情况下,向前声明可以吗?我怀疑规则实际上将变为:鼓励图书馆所有者提供一个标头,该标头专门转发声明他们认为值得的事情(强调),并且您可能不应该转发自己的声明,没有人应该声明永远声明一个模板类型。我们拭目以待。我们仍在根据我们所学到的[听不清]细节进行工作。
因此,也许尝试直接转发声明模板类型的问题可能是阻止转发声明批发的动机之一?
同样,提供“专门向前声明他们认为值得的东西的标头”听起来与此处<iosfwd>使用的方式类似,如此处(解决方案2.2),此处和此处所述。
编辑:
明确地说,我并不是说我同意或不同意Google禁止进行前瞻性声明。我只是想了解他们的基本原理,并且对此不屑一顾<iosfwd>。
就个人而言,我会按照后面在上述相同的GOTW中所述的准则(解决方案3)在任何可能的时候使用前向声明:
准则:
#include前向声明就足够时,永远不要标头。
但是温特斯的推理似乎也有一些优点。我已经处理了从第三方库转发声明的模板类型的代码,并且语法确实变得混乱(我还没有遇到Winters提到的维护问题)。OTOH,我不确定是否会阻止Google C ++样式指南中所述的所有前向声明,但是我想那对Google有用吗?
免责声明:我不是专家,还在学习。
| 归档时间: |
|
| 查看次数: |
2825 次 |
| 最近记录: |