C/C++ 多文件(模块化编程)处理
写在最前
最近接触了一个项目,需要用到多文件的处理。于是我就想着,把这些网上找来的资料整合一下,可能会有错误,恳请大家及时指出。(因为这部分我也学不太明白)
在接下来的叙述中,我们以C为例。
为什么使用模块化编程
在我们工作的时候,不可能会将所有的函数都放在一个文件下,因为你也不希望你的同事将所有的代码都放在main.c函数中。因此,我们需要利用模块的思维,将一个大功能的分为一个又一个的小功能。
从.c 和 .h讲起
我们的代码文件分为两类:.c的source和.h的header。
一般地,一个.c会对应着一个.h。
我们需要做的是,在将我们所需要实现的大功能,分解为一个又一个的小功能(模块),然后将模块们分别实现。
.h
值得注意的是:C中,header(头文件)会以.h拓展名的形式存在;而C++中有可能不会。
它们应该存放的是:
- 函数的定义
- 变量的定义
- 宏
事实上,在.h文件里实现函数是可以的。但是,在工程上,一般不会这样做。
.c
source(源代码)应该存放的是函数的实现。
单模块中示例
在下面的例子中,我们先定义了一个结构体mymap。
然后定义这个结构体变量citymap。
注意,这里是不用去include “mymap.c” 的。
// 宏定义
#ifndef MYMAP_H_INCLUDED
#define MYMAP_H_INCLUDED
#define MAX 100
#define CITYNAME_NAX 20
// 定义了一个结构体mymap。
typedef struct
{
char city_name[MAX][CITYNAME_NAX];
int now_number;
} mymap;
// 定义这个结构体变量citymap。
mymap citymap;
// 对函数的定义。
int push(char *city);
int find(char *city);
void display();
void build_map(char *file_name);
#endif // MYMAP_H_INCLUDED
而在mymap.c 中,我们需要对这个函数进行实现。
这里的实现,是我简单写了一个类似于map的操作。
大家没有必要去关注函数里具体的内容。
大家可以看到,在mymap.c文件开头中,我们需要include自己模块的头文件。然后接下来,是使用了stdio.h的静态库头文件。这里其实我是有疑问的,就是这个#include <stdio.h>应该在哪?在模块的header呢还是哪呢?希望大神可以指出呜呜呜
// include header file of module "mymap"
#include "mymap.h"
#include <stdio.h> // ?
// insert city's name into map
int push(char *city)
{
// 无用,隐去
};
// to display the map
void display()
{
for(int i = 0; i < citymap.now_number; i++)
printf("%s %d\n",citymap.city_name[i],i);
printf("%d", citymap.now_number);
}
// find the city
int find(char *city)
{
// 无用,隐去
};
void build_map(char *file_name)
{
// 无用,隐去
};
之后,再在main函数中,include这个模块的头文件。
#include <stdio.h>
#include "mymap.h"
int main()
{
char energy[100] = "energy.txt";
build_map(energy);
}
共享变量
例如,我们在module 1中定义了一个结构体。我们希望在module 2中用它。这时候,就需要共享变量。
共享的这个变量,毫无疑问,是全局变量。(因为只有全局变量才能在函数之外传递嘛)
声明和定义
声明:声明这个变量的名字,并不赋予空间;
定义:定义指出变量名字同时为变量分配存储空间,定义包含了声明。
强定义只能定义一次。局部定义的定义,属于强定义。
看例子
而例如,我们在mymap.h 中定义了一个mymap的结构体,并且定义他的变量citymap。
但是别的模块需要引用这个全局变量的话,是不能直接用的。会error,找不到这个变量的定义。因此是需要先要定义/声明这个变量。
但是,我们又不能重定义它(两次的强定义会报错)。
这时,在别的模块使用这个变量的时候,需要加上extern的关键字进行声明。