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