1

我有一个圆形标题问题,与这里已经问过的大多数问题不同。我有两个相互依赖但不是成员的类,所以不要遇到编译器无法计算类大小的问题。所以我可以使用前向声明来打破循环。

但是,我不希望客户端必须包含这两个标头才能使用我的类。标头应该是自包含的,因此用户不需要知道这种依赖关系。有没有办法做到这一点?

编辑:棘手的部分是 A 和 B 必须仅定义标题。

在标题 A.hpp

#ifndef A_HPP
#define A_HPP

#include "B.hpp"

struct A
{
    B foo() { ... }
};

#endif

在标题 B.hpp

#ifndef B_HPP
#define B_HPP

struct A;

struct B
{
    void bar()
    {
        A a = A();
        ...
    }
};

#endif

在 main.cpp

#include "B.hpp"
B().bar(); // error: 'a' uses undefined class 'A'
4

4 回答 4

3

标头 B.hpp

#ifndef B_HPP
#define B_HPP

struct A;

struct B
{
   void bar();
};

#endif

源 B.cpp

#include "A.hpp"

void B::bar()
{
   A a;
}

编辑。因此,如果您想要仅使用标头实现,请使用 AndreyT 解决方案。

于 2012-07-19T00:48:35.283 回答
2

只需在B.hpp#include "A.hpp"底部添加一个。你仍然会有一个循环包含,但现在它不会伤害任何东西。

于 2012-07-19T01:09:54.097 回答
2

如果两个头文件都包含要求其他类型完整的代码,那么在一般情况下,它不可能由自包含头文件实现。

在您的具体示例中(这太简单而无法代表),您可以简单地将定义移动B::barA.hpp

inline void B::bar()
{
    A a = A();
    ...
}

但是,当然,B定义 in的方法A.hpp看起来并不优雅。

如果 的“内联”对B::bar您很重要,那么“工业”解决方案将涉及将 的定义B::bar放入额外的头文件B_aux.hpp中。当您包含标题时,您应该在包含所有“正常”标题之后包含“辅助”标题,即main.cpp您将拥有

#include "A.hpp"
#include "B.hpp"
#include "C.hpp"
...
#include "B_aux.hpp"
...

但这显然不是一种“自成一体”的方法。

于 2012-07-19T00:49:36.287 回答
0

通常循环包含是这两种类型密切相关的标志,这可能意味着它们是一个单独的组件。如果是这种情况,那么只需将两个标头合并为组件的单个标头,首先是类型声明,最后是成员函数定义,此时两种类型都已完全定义。

于 2012-07-19T02:16:17.267 回答