循环的所有解决方案都包含了我刚刚在"这个特殊情况下所看到的依赖关系"完整的课程定义是不必要的,因为"你"只使用指向该类的指针。
我遇到了这个问题并使用前向声明修复了它。
我想知道当你需要两个类中另一个类的特定定义时你应该做什么。
另外,为什么使用指向该类的指针允许您使用前向声明而不是类定义?
答案 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,并使用简单的语法在类之间创建循环依赖。
指针实际上只是整数,类似于short
和int
,但具有由语言强制执行的特殊语义和基于CPU体系结构在编译时已知的固定大小。这使得指针声明对于编译器来说非常简单。
前向声明有助于循环依赖和实现隐藏(这也可以加快编译时间)。考虑pimpl idiom。如果没有前瞻性声明,那么隐藏实现细节就没有类型安全的方法。