前置声明是指对类、函数、模板或者结构体进行声明,仅仅是声明,不包含相关具体的定义。在很多场合我们可以用前置声明来代替#include语句。
类的前置声明只是告诉编译器这是一个类型,但无法告知类型的大小,成员等具体内容。在未提供完整的类之前,不能定义该类的对象,也不能在内联成员函数中使用该类的对象。而头文件则一一告之。
如:class Screen;
前置声明,也称前向声明(forward declaration)。在声明之后,定义之前,类Screen是个不完整类型(incomplete type),即已知Screen是一个类型,但是不知道包含哪些成员。
不完全类型只能以有限方式使用。不能定义该类型的对象。不完全类型只能用于定义指向该类型的指针及引用,或者用于声明(而不是定义)使用该类型作为形参类型或返回类型的函数。
可以通过前置声明配合指针或引用类型声明来减少编译依赖。
Never #include a header when a forward declaration will suffice.
前置声明的作用:
(1)、可以减少编译依赖、减少编译时间(如果头文件被修改,会导致多次重新编译);
(2)、可以隐藏细节;
(3)、可以减少类大小(前置声明会告诉这个类的存在,而不用提供类定义的所有细节);
(4)、减少include,防止类间相互引用形成依赖,造成编译不通过.
以下是在Google C++风格指南中对前置声明的介绍:
尽可能地避免使用前置声明。使用#include 包含需要的头文件即可。
所谓前置声明(forward declaration)是类、函数和模板的纯粹声明,没伴随着其定义.
优点:
(1)、前置声明能够节省编译时间,多余的 #include 会迫使编译器展开更多的文件,处理更多的输入。
(2)、前置声明能够节省不必要的重新编译的时间。 #include 使代码因为头文件中无关的改动而被重新编译多次。
缺点:
(1)、前置声明隐藏了依赖关系,头文件改动时,用户的代码会跳过必要的重新编译过程。
(2)、前置声明可能会被库的后续更改所破坏。前置声明函数或模板有时会妨碍头文件开发者变动其 API.例如扩大形参类型,加个自带默认参数的模板形参等等。
(3)、前置声明来自命名空间std:: 的 symbol 时,其行为未定义。
(4)、很难判断什么时候该用前置声明,什么时候该用 #include 。极端情况下,用前置声明代替 includes 甚至都会暗暗地改变代码的含义.
结论:
(1)、尽量避免前置声明那些定义在其他项目中的实体.
(2)、函数:总是使用#include.
(3)、类模板:优先使用#include.