对于类class1
的每个指针class1
,使用class1
的前向声明而不是包含{{1}}头文件,我们应该考虑哪些风险?
我只能看到优势:头文件的大小会更小。
答案 0 :(得分:13)
在班级提供者的控制之外的前向声明是有问题的!我正在使用代码库,其中使用了许多前向声明。事情最初是伟大的,前向声明的存在成为遗产:
typedef
或using alias
)。假设前向声明是通过类提供者/实现者控制下的头提供的(例如,实现提供类似于<iosfwd>
的东西),这些问题是不相关的,因为声明的中心位置可以改变。但是,让用户决定声明实体会成为遗留问题,从而导致成本高昂。
上述提供声明的方法似乎引起了一些混淆。我试着澄清一下。在我看来,实现的单元是组件(它基于John Lakos的组件符号)。组件定义一个或多个密切相关的类和/或功能。组件的实现由多个文件组成:
<iosfwd>
是跨多个组件共享的此类头的示例)。 组件的用户在某些上下文中只需要知道组件中的名称,其中包括仅声明标头。在任何情况下,用户都不会在组件中提供名称声明:组件中名称的所有声明都是组件的提供者/实现者的责任。
答案 1 :(得分:1)
我只能看到优势:头文件的大小会更小。
这不是重点。
假设您在头文件中有类声明,如
namespace MyNamespace {
class Baz;
}
class Foo {
public:
void bar(const MyNamespace::Baz & x);
};
和单独翻译单元中的定义
#include "Baz.hpp"
void Foo::bar(const MyNamespace::Baz & x) {
// actually do something with Baz
}
并且相反,头文件中包含所有内容(并且在Baz.hpp
将被更改时,将重新编译所有相关源)
#include "Baz.hpp"
class Foo {
public:
void bar(const MyNamespace::Baz & x);
};
声明,第一个版本可能有助于更快地编译代码。
特别是如果你有自己的标题和类声明,并且如果其中任何一个可能被更改,你只需要在代码库中重新编译翻译单元,而不是每个包含类型相关标题的源文件。< / p>
请注意,前向声明只能用于引用和指针。此外,还不能使用标题内联代码来解除对转发类型成员的引用。