循环包含依赖项/转发声明
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.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;
}
此外,为什么使用指向类的指针可以使用forward声明而不是类定义?
Forward声明只是编译器的名称。该概念存在,因此您可以使用尚未定义的类型。这是必要的,因为C++解析代码的方式,它继承了大量C语言的工件。C++解析器实际上只是仅向前的文本处理器,在#include
和使用宏时注入文本。这是一个概念简单的模型,使C/C++编译器在早期更容易编写。与之相比,C#/Java只需使用/inport,就可以用简单的语法在类之间愉快地创建循环依赖关系。
指针实际上只是整数,类似于short
和int
,但具有由语言强制执行的特殊语义,并且在编译时基于CPU架构已知固定大小。这使得指针声明对于编译器来说处理起来非常简单。
正向声明方便了循环依赖关系和实现隐藏(这也恰好加快了编译时间(。想想皮条客这个成语吧。如果没有前向声明,就没有类型安全的方法来隐藏实现细节。
- 如何在 C++ 中转发声明 std::set?
- C++使用默认模板参数键入别名和转发声明
- 如何转发声明枚举?
- 使用函数指针转发声明作为 lamba 声明
- 如何将枚举类转发声明为模板化类的内部类?
- 转发声明在命名空间中不起作用的替代方法
- 如何正确转发声明结构"using XXX"?
- 在类内和类外的定义处执行类转发声明是否有区别
- 为什么转发声明的好友类不能在类中引用?
- 如何访问转发声明类的成员
- 仅在标头开发中转发声明
- 无法转发声明C typedef结构-正在查找其他建议
- boost::hana 转发声明标头的用例是什么?
- 循环包含依赖项/转发声明
- c++ 使用复杂的依赖项获取正确的转发声明
- 如何转发声明依赖于变量定义的类,而变体定义又依赖于模板化类?
- 有没有办法转发声明命名空间或只是提前使其可见
- 有没有办法在不引用其模板类型的情况下转发声明指向类的指针
- 我如何转发声明boost ::精神统治
- 标题文件中大规模转发声明类别的风险是什么?