前瞻性声明和包含

时间:2010-08-09 18:33:09

标签: c++

使用库时,无论是我自己的还是外部的,都有很多带有前向声明的类。根据具体情况,同样的课程也包括在内。当我使用某个类时,我需要知道该类使用的某些对象是向前声明的还是#include(d)。原因是我想知道我是应该包括两个标题还是只包含一个标题。

现在我知道检查是非常简单的,只需编译(或遍历所有标题,直到找到有问题的对象为#include(d)或forward声明)。但是对于大型项目,简单的编译需要很长时间,并且进入每个包含文件以检查所涉及的类是否被包含或者向前声明是繁琐的,特别是如果它是几个级别的深度。为了进一步说明问题:

  

A类是B类是C类   它有一个指向Class Foo的指针

我包括A类,想知道Class Foo是否可以立即使用,或者是否必须执行以下操作:

#include "ClassA.h"
#include "ClassFoo.h"

那么,是否有一种快速简便的方法可以在不编译或进入依赖标题的情况下找到这种依赖关系? (我提出这个问题的原因之一是因为如果功能尚不存在,我想最终为VS和/或独立程序创建一个加载项)

谢谢!

3 个答案:

答案 0 :(得分:7)

在源文件中,您不应该依赖其他头文件包含的内容。

您应明确包含代码所依赖的每种类型 如果你不使用类型(即只是传递一个指针或引用),那么你不需要它的定义,所以不要包含它的头文件(你正在使用的方法的头文件至少应该有一个转发声明)。

因此,在您的特定情况下,很难说清楚 您是源文件显式使用Foo中的任何成员然后您需要包含“ClassFoo.h”否则不包括。没有必要在头文件中挖掘(它们可能会改变)。只需检查源文件使用的确切内容,并包含那些(仅限于那些)头文件。

在头文件中:首选前向声明包含。这样就可以限制/破坏循环依赖。

答案 1 :(得分:1)

实际上我发现消除尽可能多的标头包含实际上有助于更多See this answer。通过删除更多#include语句,其更清晰确切地说源文件的一部分(#includes是黑盒子 - 你永远不知道是什么链接在那里一行文字)。如果类Foo需要类Bar的实现细节,那么Foo.h 不应该包含“Bar.h”,而是只包含一个前向声明。 Foo.cpp应该包括Bar.h。

foo.h中

class Bar ; // fwd declare wherever possible

class Foo
{
  // I can haz needs Bar
  void do( Bar *bar ) ;
} ;

Foo.cpp中

#include "Foo.h"
#include "Bar.h" // I can has needs complete implementation details.

Foo::do( Bar *bar )
{
}

Bar.h

class Bar
{
  // code..
} ;

答案 2 :(得分:0)

如果您正在使用class A,那么您应该只关心基类C的私有接口(以及A中可能的其他接口。如果类设计正确,您不需要直接访问Foo,因为它将封装在C的界面中,而不会暴露给公共世界。在这种情况下,您不需要包含Foo }因为它不属于C的公共接口。如果实际上Foo在某种程度上是C的接口的一部分,那么我认为C.h也应包括Foo.h,以便客户可以使用它而无需做出您所询问的确定。