因项目需要,需要对C++的程序的文件结构有所掌握:因此在网上找了下面的文章供学习和参考。希望对刚入门的C++朋友能提供一些帮助。
转载:http://www.d2school.com/
程序是由什么组成的? 学习到今天,我们至少有两个答案:
第1,程序由代码语句组成。正是一行行的代码,组成了一个完整的程序。
第2,程序由函数组成。一个个函数之间的互相调用,最终构建出一个完整的程序。
今天我们又有一个新的回答:“程序由文件组成”。
程序为什么需要使用多个文件?
一个小的程序,可以只写一个源文件,但程序稍微一大,就需要将其中不同的逻辑实现放到不同的源文件.对于需要多人一起开发的软件,自然更需要多个源文件。
14.1 源文件和头文件
和别的一些语言不同,C,C++的代码文件有“头文件”和“代码文件”之分。二者合起来我们称为单元(Unit)文件。
扩展名为 .c 或 .cpp 的文件,主要用以实现程序的各种功能,我们称为代码文件。
扩展名为 .h 的文件,称为头文件。在头文件里主要写一些函数、数据(包括数据类型的定义)、等的声明,这样可以在多个.c或.cpp文件内共享这些函数、数据。第12章我们提过到头文件的功能。说它可以起到函数“名片夹”的作用。
大都数时候,源文件和头文件是对应出现的,比如有一个 A.cpp 的源文件,就会有一个 A.h 的头文件。这种情况在我们写应用程序时,更是常见。所以C++ Builder对此进行了强化。比如,它支持在同名源文件和头文件之间通过热键来回切换。在CB6.0里,编辑器打开对应的源文件和头文件时,将显示为同一页下的两个子页。
我们来实际动手看看源文件与头文件在CB里的对应关系。
运行 C++ Builder 6或5。
这一次我们需要一个空白的Windows工程。很有可能,在你打开CB时,它就自动为你打开了一个工程。为了不出错,我们还是亲自建一个。CB6请使用主菜单:File | New | Application;而CB5则使用:File | New Application 新建一个Windows 空白工程。 如果在这过程中CB出现是否存盘的询问,请回答不存盘。
找到“代码窗口”。如果你看到的是一个叫"Form1"的表单,请按F12,“代码窗口”将跑到前面。它的标题应该是默认的"Unit1.cpp"。正是当前代码文件的文件名。如下图:
对于CB6,还可以看到在该窗口的底部有这样一个分页:
源文件:Unit1.cpp 和头文件:Unit1.h 并列着,我们可以方便地选择。至于 "Diagram",称为“图解”。这是一个给这个源文件加配套注解,及表单上各控件的依赖关系的地方。如果是一个开发小组在进行共同开发,严格地要求每个成员为每个单元文件写上“Diagram”,可以更好地实现程序员之间的沟通。
CB5没有这些,不过下面的热键操作两个版本均一样的,要求大家记住。
按 Ctrl + F6 可以在源文件和头文件之间来回切换。请大家试试。这个简单的操作将在我们今后的编程过程中高频率地使用。
14.2 如何创建多个单元文件
前面我们在“Windows应用程序工程”中看到了头文件与源文件的匹配关系,在“控制台”的工程中,也同样存在。不过由于控制台经常只用来写一些小小的程序,所以往往只需一个源文件即可。由于只有一个源文件,所以也就不存在函数、数据在多个文件之间“共享”的需要,因此边头文件也就可以不提供。
那么,是不是只有在程序很大,或者只有在有很多人同时开发一个软件时,才需要多个源文件呢?
这就好像你家里只有两本书:《红楼梦》和《格林童话》,是把它们放在同一个抽屉里呢?还是分开放到两个抽屉里?我觉得后者是比较好的选择。因为我们常常希望家里看《格林童话》的人,最好不要去看《红楼梦》。
程序也一样,最好把不同的逻辑实现,放到不同的源文件中。
下面我们做一个实例。例子的代码我们都已经学过。目标是实现一个可以求统计值和平均值的程序。
根据我们现在所学的情况,我把这个工程中的代码分为三个源代码:
其一:主程序。就是main()函数所在的代码。这个源文件实现总的流程。我将该文件取为 main.cpp。
其二:计算总和及计算平均值的代码。这个源文件负责用户计算过程,也包括每个过程所需输入输出。该文件将被存盘为mainfunc.cpp。 意为主要功能。
其三: assifunc.cpp。表示辅助功能函数所在代码。它只提供一个函数:将用户输入的大写或小写的字母'Y'或'N' 确保转换为大写。这个函数将main()主函数内,判断用户是否继续时用到。
新CB新建一个控制台程序(如果你还开着上个程序,先选File | Close All关闭它)。CB会自动生成第一个文件,不过现在的名字为“Unit1.cpp"。
接下来是一项新工作,我们来添加两人新的单元文件,即上面说的“其二”和“其三”。
CB6 :File | New | Unit;CB5:File | New Unit。
请进行两次以上操作,CB将为我们生成新的两个单元文件:Unit2.cpp和Unit3.cpp。大家可以再试试 Ctrl + F6。(注意,第一个单元文件:Unit1.cpp 没有配套的.h文件,所以不要在该文件里尝试Ctrl + F6)。
然后选择File | Save All。全部存盘,最好不要存在CB默认的目录下。记得按以下关系重命名:
Unit1.cpp 存盘为 main.cpp;
Unit2.cpp 存盘为 mainfunc.cpp;
Unit3.cpp 存盘为 assifunc.cpp;
至于总的工程,随你便,我图方便,还是叫:Project1.bpr。
(现在我们第一次在一个工程中用到多个源文件。所以你得学会如何快速打开一个工程中某个源文件——当然,现在这三个文件都已经打开着,不过假设你有点事关闭CB,我们不希望下回打开这个工程时,你“找”不到第2和第3个文件了——请点击CB工具栏上的这个图标:,将出现源文件列表对话框,如左图)
接下来讲在这三个文件中,我们分别写些什么?大多数代码我们都已经在前面学过,所以我对代码的功能不作太多的解释。我们的重点是:三个源文件之间的代码如何实现“沟通”。
第一个文件:main.cpp 用来实现程序的主流程。
在 main.cpp 中的main()函数内,我们加入代码。
#include <iostream.h>
... ...
int main(int argc, char* argv[])
{
char ch;
int count; //求总和或平均值时,需要输入的成绩个数
do
{
cout << "1)求总和" << endl;
cout << "2)求平均" << endl;
cout << "请选择(1 或 2)";
cin >> ch;
//输入有误,重输:
if(ch != '1' && ch != '2')
{
cout << "输入有误,请重新输入!" << endl;
continue;
}
cout << "请输入个数:";
cin >> count;
//根据用户的选择,调用不同函数:
switch(ch)
{
case '1' :
CalcTotal(count); //需要调用的函数之一
break;
case '2' :
CalcAverage(count); //需要调用的函数之一
break;
}
//是否继续:
cout << "是否继续?(y/n)";
cin >> ch;
//确保转换为大写:
ch = ToUpper(ch); //需要调用的函数之一
}
while(ch == 'Y');
return 0;
}
代码中,红色部分的注释表明,主函数main()需要调用到三个自定义函数。但现在我们一个也没有定义。和往常把所有的函数定义在同一个代码文件中不同,今天我们需要把它们分开到不同的代码文件。
第二个文件:mainfunc.cpp 存放和计算有关的两个过程(函数)。
先看:CalcTotal()和CalcAverage()。这两个函数我们将在mainfunc.cpp文件内定义。你可能又忘了“定义”这个术语?呵,就是“实现”,更白点,就是在mainfunc.cpp文件内“写”这两个函数。
下面是mainfunc.cpp的内容。在我们输入以下代码时,mainfunc.cpp已经有了一些必要的内容,下面的代码,除了“#include ..”一行在文件最首外,其它均在原有内容之后添加。
#include <iostream.h> //在文件最首行
... ...
//---------------------------------------------------------------------------
//求总和的过程
//参数:n 用户需要输入的个数
void CalcTotal(int n)
{
int num;
int sum = 0;
for(int i=0;i<n;i++)
{
cout << "请输入第" << i+1 <<"个整数:";
cin >> num;
sum += num;
}
cout << "总和为:" << sum << endl;
}
//---------------------------------------------------------------------------
//求平均值的过程
//参数:n 用户需要输入的个数
void CalcAverage(int n)
{
int num;
int sum = 0;
float ave;
for(int i=0;i<n;i++)
{
cout << "请输入第" << i+1 <<"个整数:";
cin >> num;
sum += num;
}
//注意不要除0出错:
if( n >=0 )
{
ave = (float)sum / n;
cout << "平均值:" << ave << endl;
}
else
{
cout << "个数为0,不能求平均。" << endl;
}
}
//---------------------------------------------------------------------------
第三个文件:assifunc.cpp 用以存放辅助作用的函数,现在只有一个。
现在还差一个函数:ToUpper()。这个函数用来将用户输入的某个小写字母转换为大写。当然,如果用户输入的不是小写字母,那就不用转换。和上面的两个函数不同,它需要返回值。
我们把ToUpper()函数单独放在assifunc.cpp里。同样,下面的代码加在该文件中原有的代码之后。不过本文件不需要include <iostream.h> ,因为没有用到 cin,cout等。
//小写字母转换为大写
//参数: c 待转换的字符
//返回值: 转换后的字符,如果原字符不是小写字母,则为原字符
char ToUpper(char c)
{
int ca = 'A' - 'a'; //大写字母和小写字母之间差距多少?
if(c >= 'a' && c <= 'z')
c += ca;
return c;
}
至此,所有自定义函数都已完成定义(实现),而三个文件的主要内容也以确定。让我们看看示意图:
main.cpp中的main()函数调用了三个函数。回忆我们学习过的“如何调用函数”的知识,当前代码在调用一个函数时,必须能“看到”这个函数。尽管CalcTotal()、CalcAverage()、ToUpper()三个函数所在文件都在同一工程里,但是在main.cpp里的代码,还是看不到它们。想一想我们以前说的“请修理工”的比喻。现在情况是:在你所住的小区,甚至就是同一楼道里,就有一个电视修理工,但可惜你们互不认识,所以当你电视坏了,想“调用”一个修理工时,你还是找不到修理工。哎!要是有它的名片就好了。
让我们试试看,按Ctrl + F9,编辑该工程。出错!
正好是三个错。分别告诉我们调用了三个没有定义的函数(Call to undefined function ...)。
(如果你出现的是一堆错,那有可能是你没有在前两个文件内最首行写:
“#include <iostream.h>”
或者是你有些代码输入有误。)
如何消除这三个错?两种方法。
第一种方法就是以前我们在讲“如何调用函数”的时候所说的,直接在调用直接声明要调用的函数。这里写出代码,算做是一次复习,然后我们将讲该方法不好之处。
在 main.cpp 的 main()函数之前加入如下三行函数声明:
void CalcTotal(int n);
void CalcAverage(int n);
char ToUpper(char c);
int main(int argc, char* argv[])
{
... ...
}
(上例中,尽管你可以将三行函数声明写在 main()函数体内,但不建议这样做)。
如果你一切输入正确的话,现在按Ctrl + F9 或 F9将可以完成编译或运行。
对于现在这个工程,这种方法确实也不能指责它有何不利之处。问题在于,如果我们还有其它文件中代码需要调用到这三个函数,我们就不得不在其它文件中也一一写上这三行声明。所以另一种方法是:把源文件中需要对外“共享”的函数声明统一写到某个头文件,然后凡是需要用到的其它文件,直接使用“#include"语句来包含该头文件,从而获得这些函数声明。
14.3 如何写头文件
在CB中,如果你通过上小节的方法新建个单元文件,那么CB将自动同时生成源文件和头文件。其实在CB里,源文件和头文件合称为单元文件,它们有相同的文件名,而扩展名一者为.cpp,另一为.h。
14.3.1 在头文件内加入函数声明
头文件:mainfunc.h
CalcTotal()和CalcAverage()函数定义在 mainfunc.cpp文件里,所以它们的声明最好写在对应的头文件mainfunc.h内。
下面我们就来看如何在头文件mainfunc.h 内增加函数声明。
一开始,头文件内有以下这些代码。另外,我增加了一行用于标明我们新加的代码应写在哪里。
//---------------------------------------------------------------------------
#ifndef mainfuncH
#define mainfuncH
//---------------------------------------------------------------------------
/* !!!头文件中,我们新增的代码必须写在此处!!! */
#endif
和源文件中新增代码添加在最后不一样,头文件中新加代码 必须在#endif之前插入。所以本例中,加完函数声明的代码应如其下所示。(另外,CB总是在头文件的第二行留了一行空白行,我不知道它这是有意还是无意。总之这里是我们写本文件总体注释的好地方。记住,头文件像名片,用于让别人看,很有必要写得详细点)
//---------------------------------------------------------------------------
//主要操作函数
#ifndef mainfuncH
#define mainfuncH
//---------------------------------------------------------------------------
//计算总和:
void CalcTotal(int n);
//计算平均值:
void CalcAverage(int n);
//---------------------------------------------------------------------------
#endif
这就是“在头文件中声明函数”的整个过程。下面是另外一个头文件。
头文件:mainfunc.h
//---------------------------------------------------------------------------
//辅助操作函数
#ifndef assifuncH
#define assifuncH
//---------------------------------------------------------------------------
//将字符转换成大写
char ToUpper(char c);
#endif
今天我们学的是如何在头文件内声明函数,以后我们需要在头文件内声明变量,或者定义新的数据类型,它们都一样需要在上述的#endif之前加入。
14.3.2 最常见的预编译语句
现在来解释这三行话:
#ifndef mainfuncH
#define mainfuncH
#endif
中间的 #define mainfuncH 我们有点脸熟。在第五章《变量与常量》中,我们讲过用宏表示常数。语法为:
#define 宏名称 宏值
比如,定义一个∏值:
#define PAI 3.14159
这里我们学的是宏定义的另一种用法:仅仅定义一个宏,不需要给出它的值,语法为:
#define 宏名称
比如:#define mainfuncH
定义了一个宏:mainfuncH。如果你无法理解“宏”这个词,不妨就当把它解释成“记号”。即编译器通过该语句,做了一个记号,记号名称为:mainfucH。
这么做的作用是什么呢?我们继续看上下文。
#ifndef 中, if 是“如果”,n 是 no,即“还没有”,def是 define,即“定义”,那么:
#ifndef mainfuncH 意为:“如果还没有定义mainfuncH这个宏”,那么……
那么之后做什么呢?就是一直到 #endif之间的语句。
总的再来看一遍:
mainfunc.h 中的主要内容:
#ifndef mainfuncH
#define mainfuncH
void CalcTotal(int n);
void CalcAverage(int n);
#endif
当编译第一次编译mainfunc.h文件时,宏 mainfuncH 还没有定义,因些,编译器通过对 #define mainfuncH的编译而产生了宏 mainfuncH。当编译器第二次编译到 mainfunc.h文件时,宏mainfuncH 已经存在,所以该头文件被直接跳过,不会重复处理该头文件中内容,比如上面的两个函数声明。
你可能会问两个问题:第一,为什么编译器可能多次编译到同一个头文件?第二,为什么源文件,比如mainfunc.cpp就不需要用到#ifndef... #endif?
这两个问题只要回答了其中一个,另一个也就自然消解。
这是由头文件特性所决定的。头文件是用来被别人包含(include)的。谁都可以指定要包含某一头文件,这样就可能造成对该头文件的重复包含。
假设有头文件head.h。如果A文件包含了head.h,而B文件也包含了head.h,那么编译器不会在编译A和编译B时,都要对该头文件尝试编译一次。
另外,头文件本身也可以包含另一个头文件,这种情况下,各文件之间互相嵌套包含的情况就更多了。
源文件(.c或.cpp)尽管可以,但一般不被用来被别的文件包含,所以不需要在源文件中加这些语句。当然,如果需要,你也可以源文件中使用 #ifndef...#endif。
每生成一个头文件,包括在重命名它时,CB会为我们取好该头文件中,上述的宏名称,它取该头文件的全小写文件名,加上一个大写的‘H’字母,比如: "mainfuncH"。请大家不要改变该宏的名称,以免出错。
除了 #ifndef ... #endif 语句外,还有它的相反逻辑的语句:
#ifdef ... #endif 它是在如果有定义某个宏,那么,编译将继续其后的语句。
另外就像有if 语句,还有 if...else...语句一样,有 #ifdef ... #endif,也就还有这个语句:
#ifdef
... ...
#else
... ...
#endif
不过这些都和我们这里的头文件相关不大,我们暂时不讲。最后我们来解释一个名词“预编译”。
编译器在编译代码时,至少需要两遍的编译处理,其中第一次,就是专门用于处理所有以 #开头的语句,如上述的#ifndef...#endif、#define等等。这一遍处理,我们称为预编译。
14.4 如何使用头文件
事实上我们经常在使用头文件。不过,以前我们一直在使用别人的头文件,今天是第一次使用我们自已的写的头件。
以前,我们几乎每个例子,包括今天的例子中,都需要在源文件的顶部写上一行:
#include <iostream.h>
或者:
#include <stdio.h>
iostream.h和stdio.h都是CB提供给我们的头文件。这些头文件随CB安装时,被保存在固定的文件夹内。
今天的例子中,main.cpp 需要使用到在 mainfunc.h 和 assifunc.h。这是我们自己写的头文件,它们保存在我们自定的文件夹中。
包含自已写的头文件,和包含CB提供的头文件并无多大区别。
请在 main.cpp 代码顶部,加入以下黑体部分:
#include <iostream.h>
#include "mainfunc.h"
#include "assifunc.h"
//---------------------------------------------------------------------------
二者的细小区别是,包含CB提供的头文件时,用尖括号<>;而包含我们自已的头文件时,使用双引号“”。CB据此判断如何找到指定的头文件。<>相当于告诉CB,这是你自已提供的头文件,到你安装时的头文件目录下找去吧,而“”则是告诉CB,是这我自已写的头文件,请首先到我当前工程所在目录下查找,如果找不到,再到别的可能的头文件目录下找这个文件。(别的还有什么目录可能存放当前工程的头文件呢?稍后会讲。)
现在,我们让main.cpp包含了它想要的头文件,头文件内有它所需函数的正确声明,那么main.cpp中原来的这三行就多余了:
void CalcTotal(int n);
void CalcAverage(int n);
char ToUpper(char c);
请删除。 然后,按F9,程序正确编译,然后运行。这里我们不关心它的运行结果。
现在来看一眼在CB中如何设定某一工程的头文件目录。
必须先说清楚,在相当长的一段时间内,我们并不需要去进行此设置。对于CB提供的头文件,它们固定就在CB安装时自动存储的某些目录下,你只要记得包含这些头文件时,使用<>即可。对于我们自已写的头文件,我们都把它们和工程文件存放在同一目录下,暂时还没有什么理由需要把某个或某些头文件“扔”在别的目录下。所以,记住在包含自己的头文件时,对使用“”即可。
首先保证当前CB正打开着上面的那个例子工程。
然后,主菜单: Project | Options 或按 Ctrl + Shift + F11,打开“工程设置(Project Options)”对话框,并切换到“目录与条件(Directories/Conditionals)”页:
图中有关目录的设置共六行,我们说其中常用的四行。
最主要的,当然是今天所说的“头文件目录”。当 CB 编译时,当它遇到这样一行:
#include "xxxx.h"
那么,它必须找到文件xxxx.h。如果,你写的是绝对路径:#include "c:\abc\123\xxxx.h",那自然没有查找这一说,不过我们不会喜欢这样写程序,因为我们不希望源代换个位置就得一一去改那些绝对路径。事实上我们不可能把头文件到处放,总是固定那么几个目录,绝大多数就一个:所有源文件和头文件都在当前工程所在目录下。这里可以添加,删除,修改一些目录位置,CB将按本设置中的目录次序去查找头文件。
请点击“头文件目录”右边,带 "..."的小按钮。出来一个新的对话框:
($BCB) 表示Borland C++Builder 的安装目录。
在这里,你可以修改(Replace),增加(Add),删除(Delete),调整次序(向上和向下的蓝箭头)各个头文件目录。CB6还提供了对无效目录的判断,如果列表中列出的某个目录实际上并不存在对应的文件夹,则将以灰色显示,并且可以用"Delete Invalid Paths"按钮全部删除。
我们什么也不用做。点 Cancel, 放弃就是。
其它目录的设定,操作完全一样。
关于在工程中如何使用头文件,我们就说这些了。
14.5 变量在多个源文件之间的使用
前面讲的是,通过在头文件中声明函数,可以达到让这个函数被其它文件共用的作用。同样地,变量也可以在多个源文件之间“共享”。下面我们就要讲,如何通过声明变量,以达到让其它文件共用同一个变量的目的。
14.5.1 变量声明
先说说“声明变量”。好像以前的课程只教过我们:定义变量,定义函数,声明函数,没有讲过“声明变量”啊?
我们很早就学过如何定义一个变量。(5.1.2)
比如:
//定义一个整型变量:
int age;
//然后,在后面的某处代码中使用这个变量:
... ...
age = 18;
cout << age << endl;
... ...
但是,我们没有遇到过如何声明一个变量。这是因为,定义一个变量的同时,也就声明了一个变量;绝大多数的时候,我们都是可以需要某个变量时,直接定义它。
今天的情况有点不一样。我们需要在某个源文件中定义一个变量,然后,在另外一个源文件中使用这个变量。
仍以前面 age 变量为例:
//我们在 A.cpp 文件中定义了这个变量:
int age;
//然后,在 B.cpp 文件中要使用这个变量:
age = 18;
cout << age << endl;
问题就出来了:在编译 B.cpp 文件时,编译器会说:“age 这个变量没有定义啊?”——当编译器在编译 B.cpp时,它并不懂得去A.cpp里去找有关 age 的定义。
那么,能不能在B.cpp里再定义一次age变量呢?
//A.cpp文件中:
int age;
//B.cpp文件中:
int age;
age = 18;
cout << age << endl;
这样,单独编译A.cpp,或B.cpp,都可以通过。但一旦要编译整个工程,编译器又会报错:“怎么有两个 age 变量的定义啊”?
不要嘲笑编译器为什么这么笨笨。C,C++是一门严谨的的计算机语言,我们不能指望编译器会“智能”地猜测程序员的企图。
解决方法是,仅在一处定义变量,别的代码需要用到该变量,但无法看到前面的定义时,则改为“声明变量”。
声明变量的语法:
extern 数据类型 变量名
和定义变量的语法相比,多了前面的 extern 这个关键字。
extern 意为“外来的”···它的作用在于告诉编译器:有这个变量,它可能不存在当前的文件中,但它肯定要存在于工程中的某一个源文件中。
这就好像:微软公司在北京招人,微软的报名方法是:在北京的应聘者必须当天去面试,而外地应聘者则通过发e-mail先报名,然后以后再去面试。 在C,C++里,不处于当前源文件中的变量被称为外部变量。比喻中,发e-mail就相当于外部变量在某一个源中写个声明。声明什么呢?就是声明“我存在啊!虽然我现在不在这里,但是我真的存在!”
上例中,正确的代码应该这样写:
//A.cpp文件中:
int age;
//B.cpp文件中:
extern int age;
age = 18;
cout << age << endl;
变量 age 是在A.cpp文件里定义的,当B.cpp文件要使用它时,必须先声明。这就是我们讲半天课的核心。
(有些教材并不认为 extern int age; 是在声明一个变量,它们把这也称为是“定义变量”的一种,只不过它是定义了一个名部变量。我认为这样认为不好,一来它造成了学习者认为“变量可以重复定义”的错误认为,二来它也造成了不统一,函数有“定义”和“声明”两种形式,而变量都没有“声明”。
可能你会说,现在也不统一啊?函数声明没有“extern",而变量却需要?呵呵,其实恰恰相反。函数声明本来也是需要一个“extern”的,比如:
extern void CalcTotal(int n);
你在代码里这样完全正确!只不过由于函数声明和函数定义的格式区别很大,(声明没有函数体,定义则必须有函数体),所以这个extern就算不写,也可以让编译器认出来它是一个“声明”。结果就规定可以不写"extern"了。
而变量呢?
extern int age; //这是声明
int age; //这是定义
你看看,不写"extern"可不行! 就靠它来区分是定义还是声明了。
如此而已。)
14.5.2 多个文件中共享变量的实例
做一个最简单的例子。新建一个控制台工程。然后再加一个单元文件。把工程存盘为Project1.bpr,把两个源文件分别存盘为Unit1.cpp、Unit2.cpp (即,都采用默认文件名)。
程序内容是:在 Unit1.cpp 内定义一个变量,即:int age,并且,要求用户输入。在Unit2.cpp里,写一函数,OutputAgeText(),它根据 age 的值, 输出一些文本。
请问,变量 age 在哪里定义?又在哪里声明?
定义指定是在 Unit1.cpp 文件里,而声明,则可以在 Unit2.cpp内直接声明(如上例中的红色代码),也可以是在头文件 Unit1.h 里声明,然后在 Unit2.cpp 内使用 include 来包含 Unit1.h。 事实让,声明也可以放在 Unit2.h内。只要能让Unit2.cpp“看到”这个声明即可。这一点和函数的声明一个道理。
我们采用放在Unit2.cpp中的方法,该方法所需代码如下:
//Unit1.cpp 内的主要代码:
#include <iostream.h>
#include <conio.h>
#pragma hdrstop
#include "Unit2.h"
... ...
//---------------------------------------------------------------------------
int age; //全局变量,年龄
#pragma argsused
int main(int argc, char* argv[])
{
cout << "请输入您的年龄:" ;
cin >> age;
//调用Unit2.cpp中的函数,该函数根据age,作出相应输出
OutAgeText();
getch();
return 0;
}
//---------------------------------------------------------------------------
//Unit2.cpp 中的主要代码:
#include <iostream.h>
... ...
extern int age; //需要Unit1.cpp内定义的变量
//报名参加“没有弯路”的学员各行业,年龄段也各处不同,在此,我们用这个函数作为共勉!
void OutAgeText()
{
if(age < 15)
cout << "计算机要从娃娃抓起!" << endl;
else if(age < 25)
cout << "青春年华,正是学习编程的黄金时代!" << endl;
else if(age < 35)
cout << "学习编程需要热情,更需要理性!我和您一样,也在这个年龄段!"<< endl;
else if(age < 45)
cout << "活到老,学到老!何况您还未老。杀毒王王江民,不也在这个时候才开始学习电脑吗?" << endl;
else
cout << "前辈,只要您像学书法一样潜心学编程!您一定会有收获!" << endl;
}
//---------------------------------------------------------------------------
//Unit2.h 的主要代码:
//声明OutAgeText()函数,供Unit1.cpp使用
void OutAgeText();
//---------------------------------------------------------------------------
请大家完成这个工程,直到能正确运行。
现在我们得到一个印象:当我们定义了一个函数或变量之后,似乎所有的源代码文件中都可以使用它,只要你在使用之前写一下相应的声明。
这样会不会带来麻烦了?想象一下,你在A文件定义了一个变量: int i, 那么以后你在别的文件里就不能再定义这个变量了!原因前面已经说过,编译器(或链接器)会说有两个变量重名。函数也一样,尽管它有重载机制,便那也只能是有限制地允许函数重名。
事实上,上例中的 int age 是一个全局变量。关于“全局”的解释,需要引起C,C++程序的另一话题:作用范围。这是下一章的内容。在那一章里,我们将看到,大部分变量只在它一定的作用范围内“生存”,不同的作用范围的变量就可以毫无障碍地重名了。
休息休息(该点眼药水了···),然后学习本章附加一节。