使用正向参考

Using forward reference

本文关键字:参考      更新时间:2023-10-16

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

但是,我不希望客户端必须同时包含这两个头才能使用我的类。标头应该是自包含的,这样用户就不需要意识到这种依赖关系。有办法做到这一点吗?

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

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

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

在您的特定示例中(太简单而不具有代表性),您可以简单地将定义从B::bar移动到A.hpp:

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

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

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

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

但这显然不是一种"自给自足"的方法。

只需在B.hpp的底部添加一个#include "A.hpp"。您仍然会有一个循环include,但现在它不会有任何影响。

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