本文同步发表于 CSDN
目录
前言
1 多文件编程
1.1 头文件
1.1.1 头文件的组成:
1.1.2 头文件的储存
1.2 多文件编程
2 命名空间
总结
引用文章
前言
这是我的第二篇博客🙂
上篇文章写了很多开发游戏所需的函数,可是那么多函数,太麻烦了,我们怎样能简便快速地使用一个函数呢?
这就要引入c语言的一个概念:多文件编程。
1 多文件编程
稍微大一点的项目都不会是单个文件的,多文件的好处实在太多,模块开发、分工协作、代码复用、结构清晰、模块更新……
我们先认识一下c语言的文件类型:
1. 头文件(.h
):放置各种声明,用于被cpp文件包含。
2. 模块文件(.cpp
):放置一些函数定义,也称为功能模块。
3. 主程序文件(main.cpp
):程序入口,调用模块文件实现的方法。
1.1 头文件
头文件,也叫c++源文件,一般不会编译,如果cpp
文件使用了头文件,编译时就会把头文件的内容拷贝到cpp
文件中。
平时我们使用的#include<bits/stdc++.h>
就是引入头文件的代码。
1.1.1 头文件的组成:
//main.h
//预编译语句,防止重复
#ifndef MAIN_H
#define MAIN_H
//引用所需的头文件
#include<bits/stdc++.h>
#include<windows.h>
#include<conio.h>
//一些宏定义
#define ll long long
#define MAXN 10e9
#define INF 0x3f3f3f3f
#define N 501
namespace std{
//这里面的内容都是std命名空间里的
//关于命名空间请看下文
class game{
//定义一个类
public:
//一些函数和定义
void init();
bool gameover();
struct{//类内也可以定义结构体哦
string usename,password;
}use;
};
void game::init(){
//一些内容
}
bool game::gameover(){
//一些内容
}
}
#endif//结束头文件
也就是说,我们可以在头文件里写一些工具函数,然后在主函数里使用。
那么,写完的头文件应该存在哪里呢?
1.1.2 头文件的储存
快捷键ctrl+B
,可以打开当前文件的所在位置,可以看到,bits/stdc++.h
这个头文件的目录是:
好了,让我们研究研究dev-c的文件组成。
在Dev-Cpp
目录下,有一堆文件和文件夹,而大部分头文件都存储在MinGW32
下。
打开MinGW32
,我们可以看到:
其中,每一个文件夹里都有很多的头文件(share
目录里主要是和其它语言的交互,例如python
),也就是说,我们把头文件存在哪里都行。
不过据观察,dev-c++大部分的头文件都在"Dev-Cpp\MinGW32\lib\gcc\mingw32\9.2.0 "
里。
那么有一个疑问,为什么bits/stdc++.h
前面要有一个bits/
呢?
其实,bits
是一个文件夹:
这些文件的位置是:"Dev-Cpp\MinGW32\lib\gcc\mingw32\9.2.0\include\c++\"
这个文件夹里有很多耳熟能详的头文件,比如algorithm
,比如如cmath
。
而这里面的文件夹:bits
,ext
等,里面也有很多的头文件(bits
是标准库。ext
是拓展库)
我们可以尝试自己建一个文件夹,例如qwq
。
然后再里面建几个头文件:比如qwq.h
,qmath.h
,qcolor.h
等。
我们写程序的时候就可以:
#include<qwq/qwq.h>
#include<qwq/qmath.h>
#include<qwq/qcolor.h>
这样还是有点不方便。
我们可以建一个头文件all.h
,在里面这么写:
#ifndef ALL_H
#define ALL_H
#include<qwq/qwq.h>
#include<qwq/qmath.h>
#include<qwq/qcolor.h>
#endif
然后写程序的时候写一行:
#include<qwq/all.h>
就可以了。
多方便啊!
1.2 多文件编程
dev-c
有一个功能就是项目。
选择左上角的文件,然后选择新建,再选择项目。
他会出来一个这样的界面:
我们选择Console Application
。名称就叫……qwq
会有一个main.cpp
的文件。
#include <iostream>
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
int main(int argc, char** argv) {
return 0;
}
除此之外,还会有这些文件:
然后我们再选择文件/新建/类
会蹦出来qwq.cpp
和qwq.h
ctrl+s
保存,然后就会出现代码:
```qwq.h```
#ifndef QWQ_H
#define QWQ_H
class qwq{
public:
qwq();
protected:
};
#endif
```qwq.cpp```
#include "qwq.h"
qwq::qwq(){
}
现在qwq
目录下是这样的:
我们可以随便写一些代码。如:
```qwq.cpp```
#include "qwq.h"
#include<bits/stdc++.h>
using namespace std;
qwq::qwq(){
cout<<"这是一个头文件qwq!\n";
}
然后再main.cpp
下添加这个头文件。
```main.cpp```
#include "qwq.h"
int main(int argc, char** argv) {
qwq();
return 0;
}
效果:
dev-c++
会同时编译qwq.cpp
和main.cpp
两个文件:
g++ -c main.cpp -o main.o
g++ -c qwq.cpp -o qwq.o
g++ main.o qwq.o -o out
而qwq.h
的内容已经被编译器拷贝到qwq.cpp
和main.cpp
中了。
这就是多文件编程!
2 命名空间
举个栗子:
记得在一个课外班学习时,班级里有两个叫做张伟的同学,老师不得不想了一个办法,当叫长得高一点的张伟时,就说:高张伟,长得矮的就叫做:矮张伟。
同样的情况也出现在 C语言 中。比如你写一个叫做h()
的函数,但当你编译的时候,你惊奇地发现,这个函数竟然已经有了!
因此,引入了命名空间这个概念,专门用于解决上面的问题,它可作为附加信息来区分不同库中相同名称的函数、类、变量等。使用了命名空间即定义了上下文。==本质上,命名空间就是定义了一个范围。==
实例:
#include<bits/stdc++.h>
namespace qwq{
int a=1;
}
using namespace std;
int main(){
int a=3;
cout<<qwq::a;
return 0;
}
这个程序运行后,会输出1
因为输出的变量a
是在命名空间qwq
中的,而在主函数中定义的a
则是在标准命名空间中的。
那么假如我们换一种代码:
cout<<a;
这回的输出就是3
了。
很神奇吧,其实命名空间内可以有很多内容,比如函数、类,甚至嵌套命名空间!
#include<bits/stdc++.h>
namespace qwq{
int a=1;
namespace qwq1{
int a=3;
}
}
using namespace std;
int main(){
cout<<qwq::a<<" "<<qwq::qwq1::a;
return 0;
}
这回的输出是1 3
如果嫌太累,你可以在主函数上面加上一个using namespace qwq;
然后就不用再写qwq::a
了
但是命名空间也不能滥用,下面是一个错误事例:
#include <bits/stdc++.h>
using namespace std;
namespace qwq{
int a = 100;
int orz(){
cout<<"a="<<a<<endl;
}
namespace qwq1{
int a =20;
int orz(){
cout<<"a="<<a<<endl;
}
}
}
using namespace qwq;
using namespace qwq::qwq1;
int main(){
orz();
return 0;
}
这样会出错:会显示 a 变量和 orz函数 “was not declared in this scope”
,编译器不知道要去使用哪个 a 和 fun()。
所以要不然就不用using
,要不然就之using
一个命名空间。
总结
本来是准备写一下自己的头文件的,没想到牵扯出来这么多东西,既然这样,那编写自己的头文件
就放在下篇文章吧!
还是感谢引用文章的作者,说实话这篇文章和上篇文章我都是在边学习边写的。
另外,做一些无聊的统计:
本篇文章共5550
字,275
行,10
图片,共花费时间9
小时。
大佬,6