c++之前向声明,深入理解

声明与定义

首先来了解一下声明和定义的区别。

声明(declaration)用于向程序表明变量的类型和名字。定义也是声明,当定义变量的时候我们声明了它的类型和名字。可以通过使用extern声明变量名而不定义它。不定义变量的声明包括对象名、对象类型和对象类型前的关键字extern。

变量的定义(definition)用于为变量分配存储空间,还可以为变量指定初始值。在程序中,变量有且仅有一个定义。

extern声明不是定义,也不分配存储空间。事实上它只是说明变量定义在程序的其他地方。程序中变量可以声明多次,但只能定义一次。

#include

#include 是一条预处理指令,即在预处理阶段 在该指令处展开被包含的头文件。

有两种使用方式:

  1. #include <xxx.h>
    第一种方法将待包含的头文件使用尖括号括起来,预处理程序会在系统默认目录或者括号内的路径查找,通常用于包含系统中自带的公共头文件。

  2. #include “xxx.h”
    第二种方法将待包含的头文件使用双引号引起来,预处理程序会在程序源文件所在目录查找,如果未找到则去系统默认目录查找,通常用于包含程序作者编写的私有头文件。

前向声明

前向声明指在A程序中引入新的类型B,但是此时B并不是一个完整清晰的类;只知道有这么一个类,但是不清楚它的具体函数接口实现以及成员变量;
因此不能定义一个B的对象,只能使用指针和引用的方式
直到后面找到B的定义我们才真正知道B的具体实现,才可以调用它的构造函数定义对象;

举一个栗子:
c++的文件IO类定义在 fstream 头文件中;
但是 fstream 中定义的是模板类 basic_ifstream 和 basic_ofstream ,我们使用的却是 ifstream 和 ostream。
实际上 ifstream 和 ofstream 是 iosfwd 头文件中实例化模板类后取的别名,iosfwd 包含在 iostream 中。
而当我们单独包含 iostream 时使用 ifstream 会报错,类型未定义;
只包含 fstream 时会报未声明的标识符;
因为iostream并未include fstream,因此找不到类型定义。实例化时使用的正是 前向声明

前向声明的应用

1. 中断循环引用

假如有类A在a.h中,类B在b.h中,而类 A 和 B 都需要调用对方。
而循环包含是禁止的,也编译不过。这时候就需要用到前向声明了。

一个头文件include另一个,另一个则使用前向声明。
例:

// a.h
#pragma once

#include <stdio.h>
#include "b.h"

class A
{
public:
	void funcA() {
		printf("This is A.\n");

		b.funcB();
	}

	void funcB() {
		printf("A is called.\n");
	}

	B b;
};
// b.h
#pragma once

#include <stdio.h>

class A;

class B
{
public:
	void funcA();

	void funcB() {
		printf("B is called.\n");
	}

	A *a;
};

然后需要实际用到的时候就在cpp中include;

// b.cpp
#include "b.h"
#include "a.h"

void B::funcA() {
	printf("This is B.\n");

	a = new A;
	a->funcB();

	delete a;
}

2. 避免暴露头文件

如果类A用到了某个内部的类,打包时就不得不把内部的头文件也对外开放
库的开发者肯定不希望对外暴露内部的细节 所以需要利用前向声明跳过

接上面的例子,我们编译成静态库。
然后使用这个静态库时只需包含b.h就可以使用了。
而类A中的实现完全被隐藏了起来。

3. 减少构建时间

您可以通过#包含已经包含函数声明的头文件,将函数的声明输入到当前的.cpp或.h文件中。

但是,这会减慢编译的速度,特别是当您将头包含到程序的.h而不是.cpp中时,因为所有包含您正在编写的.h的.h的内容最终都会#包括您编写的所有标头。

突然之间,编译器就有了包含页和页的代码,即使您只想使用一两个函数,也需要编译它们。

为了避免这种情况,您可以使用前向声明,只需自己在文件顶部键入函数的声明即可。

如果您只使用几个函数,这确实可以使您的编译速度比始终包含头的#更快。

对于真正的大型项目,差异可能是一个小时或更多的编译时间,减少到几分钟。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值