C++自学34:源文件与头文件(pragma/ifndef/endif/ifdef)

本文所有操作都在vs2019下进行,在vs中“头文件”和“源文件”两个文件夹是为了方便管理,假如把cpp文件放到“头文件”文件夹中,这也是没有任何问题的

.cpp结尾的就是c++的源文件
.c结尾的就是c语言的源文件,在vs中如果想创建c的源文件,只能选择创建c++文件,然后通过修改后缀名的方式,将其cpp改成c,点c的源文件,只能运行c语言的代码,任何关于c++的语法和头文件(比如iostream)都无法使用

用java对比的话,每一个cpp或者c文件,都相当于java当中的一个类

下面有源文件,分别是a.cpp和b.cpp
b.cpp源码如下

//b.cpp
#include <iostream>
void b1() {
    
    
	std::cout << "b.cpp->b1()" << std::endl;
}

a.cpp中调用b.cpp中的方法

void b1();//此处必须要先声明才能使用
int main() {
    
    
	b1();
}

我们会发现,“声明”这个操作特别的不友好,假设b.cpp中函数特别多,那么a.cpp上面就要声明很多函数,为了解决这个问题,我们使用头文件来解决,在“头文件”文件夹右键新建,选择头文件,通常头文件名称与源文件名称相同,本文新建b.h,内容如下

#pragma once//这个关键字下文会有说明
void b1();

有了头文件之后,a.cpp的代码改成下面这样,原因是因为#include是将b.h文件中的内容复制过来,和#define差不多

#include "b.h";//注意此处是双引号,而不是尖括号
int main() {
    
    
	b1();
}

头文件中不仅可以声明,也可以定义,但是通常不这么做,因为很可能会产生冲入,比如当a.cpp当中也有b1这个方法的时候,切记:在同一个工程中,声明可以多次,定义只有一次

站在编译器的角度:编译器不会编译头文件,只有在cpp文件中使用h文件的时候,编译器才将这个h文件的内容复制过来,假设有一个h文件,里面随便写任何东西,但是没有cpp文件使用它,此时编译也不会报错,由此可以证明编译器不会编译这个h文件

在h文件中定义全局变量

//b.cpp文件中代码如下
#pragma once
void b1();
extern int mys;//和上边的代码相比,多出了这行代码

新建一个c.cpp文件

扫描二维码关注公众号,回复: 12468289 查看本文章
//c.cpp文件
#include "b.h"
void c1() {
    
    
	mys++;
}

在a.cpp的main函数下执行下面代码

#include <iostream>
#include "b.h"
void c1();
//注意此处,b.cpp中的extern是声明,必须还要有一个定义才行,所以在此处对
//mys进行定义,这样,a.cpp和c.cpp就能共用一个mys变量了
int mys = 0;
int main() {
    
    
	mys++;
	c1();
	std::cout << mys << std::endl;
}

#pragma once:表示在其他的同一个文件中,只引用我这个文件一次
解决循环依赖问题,假如a.h文件引用了b.h文件,而b.h又引用了a.h,那么根据预处理命令的语义,就会出现a一直循环引用b,b一直循环引用a的情况,此时需要#pragma once来解决

//b.h
#pragma once
void b1();

由于#pragma once的存在,下面的a.cpp写多少次include都没有关系

//a.cpp
#include "b.h"
#include "b.h"//多次include没有关系,因为b.h中写了pragma once
#include "b.h"
#include "b.h"
#include "b.h"
int main() {
    
    
	
}

注意:有些编译器不支持pragma,此时使用#ifndef和#endif来解决,不过我觉得写笔记太麻烦了,就没有在笔记中记录,但是ifndef相对pragma比,有一个优势,就是它可以定义在任意代码块,而pragma是整个文件,还有一个叫#ifdef,少个n,不过通常ifndef和ifdef用于版本控制,比如一个游戏,有vip版本和普通版本


18.3

猜你喜欢

转载自blog.csdn.net/u011624903/article/details/111054862
今日推荐