使用前向参考

时间:2012-07-19 00:43:56

标签: c++ header-files

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

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

编辑:棘手的部分是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 个答案:

答案 0 :(得分:3)

Header 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解决方案。

答案 1 :(得分:2)

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

在您的具体示例中(过于简单而无法代表),您只需将B::bar的定义移至A.hpp

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

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

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

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

但显然,这不是一种“自足”的做法。

答案 2 :(得分:2)

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

答案 3 :(得分:0)

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

相关问题