如何避免标题耦合

时间:2010-06-16 14:25:14

标签: c++ c visual-studio visual-studio-2008 visual-c++

我正在努力解决这个问题,因为我似乎无法在网上找到一个好的资源。

我不完全理解这个问题,因为我从来没有解决过这个问题所以我会尝试尽可能地描述它。

前一段时间我遇到了一个问题,即标题被忽略了,因为“它们已经被调用过一次,因此当它们被另一个文档再次调用时,它被忽略了,因此抛出了错误”

我从来没有完全明白,因为你可以多次调用标题而不会抛出错误

那么header1.h

#ifndef _FCLASS_
#define _FCLASS_
class firstClass {
     ...//declaration
}

#endif

header2.h

#ifndef _SCLASS_
#define _SCLASS_

#include "header1.h"

class SecondClass:firstClass{
     ...//declaration
}

#endif

header3.h

#ifndef _TCLASS_
#define _TCLASS_

#include "header1.h"
class thirdClass:firstClass{
     ...//declaration
}
#endif

在上面的示例中,header1类被调用了两次,并且不应该抛出任何错误。即使header1被声明一次,它也可以被多个头使用。

所以我的问题是,在什么情况下,如果文件已经被声明一次,那么文件实际上可以忽略它。

此类问题是否仅适用于包含标题的.cpp文件?

2 个答案:

答案 0 :(得分:5)

这种情况最常发生在有标题周期时(两个标题彼此包含最可能的情况)。

仅举例说明,真实的例子通常更为复杂。

A.H:

#ifndef A_INCLUDED
#define A_INCLUDED

#include "B.h"

class A
{
};

class C
{
    B b;
}
#endif

B.h:

#ifndef B_INCLUDED
#define B_INCLUDED

#include "A.h"

class B : public A
{
};
#endif

在这种情况下,无论您包含哪个标头,都存在循环依赖关系,导致无法编译。如果你包括A.h,它包括B.h. B.h然后包括A.h但是包含警卫阻止它再次被包括在内。那么它继续编译B.h并在它不知道class A时失败。如果首先包括B.h,则相反的情况适用。

编辑:我应该提到这通常是通过将一个或两个标头中的逻辑重构为另一个标头,和/或使用前向声明而不是实际包含来解决的。

答案 1 :(得分:2)

我能想到一个场景。如果header1.h具有由条件编译排除的部分,并且这些条件通过随后包含的头文件中的声明而更改。以后对header1.h的包含将被其包含守卫跳过,并且它将无法声明可能导致错误的条件部分。