循环包括依赖/前向声明

时间:2017-09-01 03:08:12

标签: c++

循环的所有解决方案都包含了我刚刚在"这个特殊情况下所看到的依赖关系"完整的课程定义是不必要的,因为"你"只使用指向该类的指针。

我遇到了这个问题并使用前向声明修复了它。

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

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

2 个答案:

答案 0 :(得分:2)

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

以下是一个不可能的案例:

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....尝试构建。

如果你使用指针,你不需要知道它们的大小;指针的大小始终相同,具体取决于您所在的平台。系列消失了,因为需要明确地创建堆中的对象。

答案 1 :(得分:0)

  

我想知道当你需要特定的东西时你应该做什么   两个类中其他类的定义。

可以使用现代编译器中的前向声明和延迟定义来完成。许多较旧的编译器只允许指针和对前向声明类型的引用。

这是一个人为的例子:

<强> A.hpp

class B;

class A
{
public:
    int32_t Value;

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

    int32_t Add(B b) const;
}

<强> B.hpp

#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进行对比,您只需使用/ import,并使用简单的语法在类之间创建循环依赖。

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

前向声明有助于循环依赖和实现隐藏(这也可以加快编译时间)。考虑pimpl idiom。如果没有前瞻性声明,那么隐藏实现细节就没有类型安全的方法。