假设我有一个包含3个项目X
,Y
和E
的解决方案。
E
将生成可执行文件,X
和Y
将生成静态库,以使Y
包含X
和{{1}的头文件}包括E
的头文件。
现在,我的问题是:为什么我必须在Y
中包含X
的头文件的目录?
答案 0 :(得分:4)
原因如下:
Y
中的某个函数可能会接受X
中声明的类型的参数(或返回值)。 E
时创建这些参数(或返回值)对象。 X
中绝对需要来自E
的标头文件。 答案 1 :(得分:1)
有时可以重构C ++的头文件以使用前向声明来避免您描述的情况。以下是一个示例:C++ header dependency tricks。
一个简单的案例:
class X {
//...
};
// #include <X.h> -- remove this
class X; // add forward declaration
class Y {
X *m_px; // must be a pointer, not a value,
// otherwise the size of X would need to be known
//...
};
#include <X.h> // need to add it here
//...
答案 2 :(得分:1)
如果构造Y使其对X的依赖性完全封装,则可以避免这种情况。根据X和Y的具体情况,这可能是也可能是不可能的。但是如果Y给E提供的接口不需要在其中包含X的任何细节,那么E项目甚至不需要间接包含来自X的标题。在这种情况下,只有Y(.c或.cpp文件)的实现文件将包含来自X的标题。在Y标题中对X中的类型使用前向声明可以帮助在Y中实现X的这种封装。 / p>
这是一个很好的目标,但它可能并不总是可能,即使有可能,它可能比你(或你的管理层)想要提出的更多努力。
答案 3 :(得分:0)
简答:“为什么我必须在E中包含X的头文件目录?”......你不应该这样做。 Y的客户不应该知道Y依赖于X.
长答案:只有当Y的接口(签名)使用X标题中声明的内容时,才需要在E中包含X的标题。但是如果Y的标题是“正确构造”,然后它们将在Y标题本身中包含X的标题,并且您不必明确地在E中包含X标题(包括Y标题将自动包含X标题)。
通过“正确构造”,我的意思是如果Y中的Y1.h中的签名依赖于(例如)X3.h和X7.h,那么Y1.h应该包括那些文件(直接间接地)。这样,Y1.h的任何客户端都不必知道它的依赖关系是什么,并且必须分别包含这些依赖关系。作为一个简单的测试,由以下行组成的.cpp应该编译没有问题:
#include "Y1.h"
一个好的做法是在包含Y1.cpp中的任何其他文件之前#include“Y1.h”。如果Y1.h缺少依赖项,编译器会通知你。