我有一个圆形标题问题,与此处已经提到的大多数问题不同。我有两个相互依赖的类,但不是成员所以不要遇到编译器无法计算类的大小的问题。所以我能够使用前向声明来打破这个循环。
但是,我不希望客户端必须包含这两个标头才能使用我的类。标头应该是自包含的,因此用户不需要知道这种依赖性。有没有办法做到这一点?
编辑:棘手的部分是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'
答案 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)
通常,圆形包含是两种类型紧密相关的标志,这可能意味着它们是单个组件。如果是这种情况,那么只需将两个标头合并到组件的单个标头中,首先是类型声明,最后是成员函数定义,两种类型都已完全定义。