繁体   English   中英

通函包括依赖性/转发声明

[英]Circular include dependency/Forward Declarations

循环的所有解决方案都包括依赖关系,我已经在“这种特殊情况”下看到过,不需要完整的类定义,因为“您”仅使用指向该类的指针。

我遇到了此问题,并使用前向声明对其进行了修复。

我想知道当您需要两个类中另一个类的特定定义时您应该怎么做。

另外,为什么使用指向类的指针允许您使用前向声明而不是类定义?

在什么情况下,您需要两个类都预先知道的规范?

一种不可能的情况如下:

class A
{
    B m_b;
};

class B
{
    A m_a;
};

但这是不可能的,因为类A的大小取决于类B的大小,而类B的大小取决于类A的大小A myA; myA.m_b.m_a.m_b.m_a.... A myA; myA.m_b.m_a.m_b.m_a....当您尝试构造其中一个时。

如果使用指针,则不需要知道两者的大小。 根据所使用的平台,指针的大小始终相同。 并且该系列消失了,因为需要显式创建堆中的对象。

我想知道当您需要两个类中另一个类的特定定义时您应该怎么做。

这可以通过现代编译器中的前向声明和延迟定义来完成。 许多较早的编译器仅允许使用指针和引用来转发声明的类型。

这是一个人为的示例:

丙型肝炎

class B;

class A
{
public:
    int32_t Value;

    A(int32_t value) : Value(value) { }

    int32_t Add(B b) const;
}

乙型肝炎

#include "A.hpp"

class B
{
public:
    int32_t Value;

    B(int32_t value) : Value(value) { }

    int32_t Sub(A a) const;
}

AB.hpp

#include "A.hpp"
#include "B.hpp"

inline int32_t A::Add(B b) const
{
    return this->Value + b.Value;
}

inline int32_t B::Sub(A a) const
{
    return this->Value - a.Value;
}

另外,为什么使用指向类的指针允许您使用前向声明而不是类定义?

转发声明只是编译器的名称。 这个概念存在,所以你可以使用没有被定义的类型。 这是必需的,因为C ++解析代码的方式是从中继承大量C语言的产物。 C ++解析器实际上只是仅向前的文本处理器,它们在#include和使用宏时会注入文本。 这是一个概念上简单的模型,使早期的C / C ++编译器更易于编写。 将此与C#/ Java进行对比,您仅在其中使用using / import并通过简单的语法在类之间愉快地创建循环依赖关系。

指针实际上只是整数,类似于shortint ,但具有由语言强制执行的特殊语义和基于CPU体系结构在编译时已知的固定大小。 这使得指针声明对于编译器来说非常简单。

前向声明有利于循环依赖和实现隐藏(这也可以加快编译时间)。 考虑一下pimpl习惯用法 没有前向声明,就没有类型安全的方法来隐藏实现细节。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM