单独编译
C++和C语言一样,允许甚至鼓励程序员将组件函数放在单独的文件中,然后将它们链接成可执行程序,通常,C++编译器既编译程序,也管理链接器。
通常可以将一个程序分成三个部分:
- 头文件: 包含结构声明和使用这些结构的函数的原型。
- 源代码文件: 包含与结构有关的函数的代码。
- 源代码文件: 包含调用与结构相关的函数的代码。
头文件中常包含的内容:
- 函数原型
- #define和const定义的符号常量
- 结构声明
- 类声明
- 模板声明
- 内联函数
包含头文件时,我们可以使用""
或者<>
两种方法,当使用""
时,编译器首先查找当前的工作目录(或者其他目录,和取决于编译器),如果在这里没有找到头文件,那么将在标准位置查找。而使用<>
时,编译器在存储标准头文件的主机系统的文件系统中查找。因此,在使用自己编写的头文件时,应该使用""
的方法而不能使用<>
。
头文件管理
在同一个文件中,只能够将同一个头文件包含一次,请注意是否会在同一个文件中包含同一个头文件多次,因为在同一个文件中包含头文件两次的话,那么将会发生变量声明、函数声明等等的冲突。
一种有效的方法是,在每一个编写的头文件中,可以包含一个头文件独有的宏定义声明,比如说下面的头文件:
//exam1.h 头文件
#ifndef EXAM1_H
#define EXAM1_H
typedef struct polor1{
double distance;
double angle;
} polar;
typedef struct rect1{
double x;
double y;
}rect;
polar rect_to_polar(rect);
void show_polar(polar);
#endif
可以使用C/C++预编译指令来构造防护方案,如果已经包含了此文件,那么EXAM1_H将已经被定义,然后因为再此包含此文件由于预编译指令#ifndef EXAM1_H
表示,如果没有定义EXAM1_H
,那么将把下面#endif
之前的声明包含在文件中,如果已经定义了,那么将忽略这一部分,就像是if else
语句一样(实际上还有#elif
和#else
语句)。
连接编译的实现
//exam1.cpp 函数定义文件
#include<iostream>
#include"exam1.h"
#include<cmath>
using namespace std;
polar rect_to_polar(rect a)
{
polar result;
result.distance=sqrt(pow(a.x,2)*pow(a.y,2));
result.angle=atan2(a.y,a.x);
return result;
}
void show_polar(polar a)
{
const double conver=57.29577951;
cout<<"The distance is: "<<a.distance<<endl;
cout<<"The angle is: "<<a.angle*conver<<endl;
return;
}
//exam2.cpp主函数文件
#include<iostream>
#include"exam1.h"
using namespace std;
int main(void)
{
rect a;
polar b;
cout<<"Please enter the polar's X and Y's value: ";
while(cin>>a.x>>a.y)
{
b=rect_to_polar(a);
show_polar(b);
cout<<"The next data: \n";
}
while(cin.get()!=EOF);
return 0;
}
以上两个是主函数文件和函数定义文件。
为了便于操作,在Dev C++上实现连接编译
实际上我不知道怎么在vscode上实现多文件连接编译。
接下来的问题是怎么实现链接编译
- 首先,打开Dev c++,选择左上角文件—新建—项目
- 选择Empty Project然后选择C或者C++项目创建即可。
- 然后创建三个文件用来写拆分的代码。结果就和上图一样。
- 在这个时候点击编译运行,编译器就会自动进行连接编译了。
C++ Primer Plus上说,虽然我们讨论的是根据文件进行单独编译,但是C++标准使用术语翻译单元而非文件,文件并不是计算机组织信息的唯一方式。
关于多个库的链接
关于多个库的链接,C++标准允许每个编译器的设计人员以它认为合适的方式实现名称修饰,因此,不同编译器创建的二进制代码模块很可能无法正确的链接,两个编译器将为一个函数生成不同的修饰名称,两个函数实际上并不匹配,因此,在链接编译模块时,请确保所有对象文件或库都是由一个编译器生成的,如果有源代码,通常可以使用一个编译器重新编译来消除连接错误。