1.C++--关于文件间共享代码的方法

来源:互联网 发布:铁岭网络预约出租汽车 编辑:程序博客网 时间:2024/06/05 09:51

前置引述

1.为了提高代码的可扩展性、可维护性等,c++语言支持分离式编译机制,该机制允许将程序分割成若干个文件,每个文件可被独立编译。
2.可分离式编译机制会引出一个问题,那就是文件间的代码共享问题,比如,我在A文件中命名一个变量a,想要在B文件中使用这个变量a,怎么办?

正文

C++是如何支持跨文件通信的?

为了支持分离式编译、同时也为支持文件间的代码共享,C++将声明定义区分了开来。
声明:使得名字为程序所知,一个文件如果想使用别处定义的名字则必须包含对那个名字的声明。
定义:负责创建与名字关联的实体。

变量声明规定了变量的类型和名字,在这一点上定义与之相同。但是除此之外,定义还申请存储空间,也可能会为变量赋一个初始值。

如果想声明一个变量而非定义它,就在变量名前添加关键字extern,而且不要显示地初始化变量:

extern int i;   //声明i而非定义int j;  //声明并定义

任何包含了显示初始化的声明即为定义。我们能给由extern关键字标记的变量赋一个初始值,但是这么做也抵消了extern的作用。extern语句如果包含初始值就不再是声明,而是一个定义。

注意:在函数体内部,如果试图初始化一个extern标记的变量,将引发错误。
注意:变量有且只能被定义一次,但是可以多次声明。

声明和定义看起来微不足道,但实际上却非常重要。如果要在多个文件中使用同一个变量,就必须将声明和定义分离。

实验

实验一

Test.h文件

//Test.h#ifndef _TEST_H__#define _TEST_H__extern int i = 5;#endif

在这个头文件中声明并定义了一个整型变量。

Test.cpp文件

//Test.cpp#include <iostream>#include "Test.h"void output(){    std::cout << "蛤?" << std::endl;}

在这个实现文件中包含了Test.h头文件,并输出一条语句。

main.cpp文件

//main.cpp#include <iostream>#include "Test.h"void main(){    std::cout << "啊蛤?" << std::endl;}

在这个实现文件中包含了Test.h头文件,并输出一条语句。

————编译结果————

错误 2 error LNK1169: 找到一个或多个多重定义的符号
错误 1 error LNK2005: “int i” (?i@@3HA) 已经在 main.obj 中定义

很明显,编译出错,至于为什么,就在于变量的定义和声明没有分离。
我们知道,c++编译器在编译文件时,是将.cpp文件逐个编译成.obj(在windows中)文件,然后再链接到一起形成.exe文件(在windows中)。那么,在这个例子中,生成了两个obj文件,一个是main.obj,一个是Test.obj。但两个obj文件同时包含了头文件Test.h,而Test.h直接声明并定义了变量i,而C++规定变量有且只能被定义一次,那么main.obj中定义了一次,Test.obj中又定义了一次,必然报错。

实验二

Test.h文件

//Test.h#ifndef _TEST_H__#define _TEST_H__extern int i;#endif

在这个头文件中声明一个整型变量。

Test.cpp文件

//Test.cpp#include <iostream>#include "Test.h"int i = 5;  //定义变量void output(){    std::cout << i << std::endl;    std::cout << "蛤?" << std::endl;}

在这个实现文件中包含了Test.h头文件,定义了变量i,并输出两条语句。

main.cpp文件

//main.cpp#include <iostream>#include "Test.h"void main(){    std::cout << i << std::endl;    std::cout << "啊蛤?" << std::endl;}

在这个实现文件中包含了Test.h头文件,并输出两条语句。

————编译结果————

5啊蛤?
0 0