一、多文件结构的源代码组织

  一个C++程序开发工程(project)可以包含多个源程序文件,一个源程序文件(.cpp)可以包含多个函数。一个函数只能集中放在一个源程序文件中,不能将其定义代码拆开存放在不同文件中。一个程序开发工程可以包含很多函数,但只能有一个主函数,其中函数名必须为main。

  使用编译器将C++语言翻译成机器语言。编译时,同一源程序文件中的所有函数被统一编译,因此一个源程序文件称为一个编译单元。一个C++ project可以多个源程序文件cpp,每个cpp编译后产生一个目标程序文件(obj)。目标程序是机器语言的程序,通常不同厂家CPU的机器语言是不一样的。相同的C++源程序可被不同的编译器编译,生成不同机器语言的目标程序运行在不同CPU架构上。

1、外部函数和外部全局变量

  在多文件结构中,一个文件中定义的函数可以被其他文件中的函数调用。可被其他文件调用的函数称为外部函数。一个文件中定义的全局变量也可以被其他文件中的函数访问。可被其他文件访问的全局变量称为外部全局变量。调用外部函数需要“先声明、在调用”,访问外部全局变量也需要 “先声明,在访问”。声明的作用是将外部函数或外部全局变量的作用域延申到本文件来。

声明外部函数和外部全局变量的语法细则如下:

  1)声明外部函数原型,声明是可以使用关键字extern,也可以不用,两者的语法作用完全相同。也可以通过头文件将大量外部函数声明进来。

      extren void RectCost();

      extren double CircleCost(double r);

  2) 声明外部全局变量,声明时必须加上关键字extren,另外不能初始化,否则就变成了另一个全局变量定义语句,连接时会出现两个全局变量重名的错误。

      extren double totalCost = 0;

2、静态函数与静态变量

  多文件结构中,源程序文件中定义的函数默认是外部函数,可以被其他文件中的函数调用;所定义的全局变量默认都是外部全局变量,可以被其他文件中的函数访问。外部函数和外部全局变量被多文件结构中的所有文件共享,其他文件只要经过声明就可以使用这些函数和变量。因此多文件结构中所有外部函数和外部全局变量不能重名,外部函数和外部全局变量之间也不能重名。

  某些情况下,程序员需要在源程序文件中定义一些只能自己调用的函数和全局变量时,就可以使用关键字static将他们定义成静态函数静态全局变量。另外C++语言还可以定义静态局部变量

  1)静态函数,定义函数时在函数头前面加关键字static,该函数就被定义成静态函数。静态函数只能被本文件内部的其他函数调用,其他文件不能调用,即使经过声明也不行。

      static void RectCost();

  关键字static将所定义的函数作用域限定在本文件范围内,禁止延申到其他文件。合理定义静态函数,可以防止其他文件对该函数的误调用。不同文件中的静态函数可以重名。

  2)静态全局变量,定义全局变量时前面加关键字static,该全局变量就被定义成静态全局变量。静态全局变量只能被本文件内的函数访问,即使经过声明也不行。

      static double r1,r2;

  3)静态局部变量,定义局部变量时前面加关键字static,该变量就被定义成静态局部变量。局部变量的静态和非静态与全局变量的静态和非静态含义不一样。普通局部变量的作用域和生命期都是函数的块作用域(存储在自动存储区,即栈中),静态局部变量程序执行立即分配空间,知道程序执行结束才被释放(同全局变量一样,存储在静态存储区)。静态局部变量的作用域为块作用域,生命期为全局存在。

      static int y = 0;

  函数中的静态局部变量定义语句只会在程序一开始执行一次,后面不会在重复执行。如果函数被多次调用,其中的静态局部变量可以保留上次调用结束时的值,因为它的内存单元在程序执行一开始即被分配并初始化,知道程序执行结束才被释放,其中的数据也会一直保留下来。仔细分析就会发现,静态局部变量实际上是一种被某个特定函数访问的全局变量。

二、编译预处理指令

  在正式编译C++源程序之前,编译器将预先处理一些特殊指令,这些指令的作用是用来告诉编译器如何编译本程序,它们被称为编译预处理指令。编译器在处理完所有的编译预处理指令之后才进行正式编译。常见的编译预处理指令有三种,它们分别是文件包含指令(include)、宏定义指令(#define)和条件编译指令(#ifdef)。

1、文件包含指令

  程序员可以使用文件包含指令将某个指定文件的内容插入到程序代码的当前位置,通常是用于将某头文件(.h)插入到源程序文件(.cpp)中。

      #include<filename>      //缺省路径时,编译器将到标准目录下搜索指定文件。

     或 #include "filename"     ////缺省路径时,编译器将到当前目录下搜索指定文件。如果搜索不到指定文件再去标准目录下搜索。

  文件名通常不写完整的全路径,而是使用默认路径,即只写头文件的文件名。通常头文件被集中存放在两个目录下:一个是C++编译器安装目录的include子目录下,该目录称为标准目录;另一个是源程序文件所在的目录,称为当前目录。文件包含指令以“#”开头,单独写一行,不假分号“;”结束符。

2、宏定义指令

  C++源程序中,允许用一个标识符来表示一段代码文本,这就称为一个。其中标识符为宏名,所白表示的代码文本称为宏文本。

  宏需要先定义在使用。程序员可以通过宏定义指令(#define)来定义一个新的宏,可以通过宏删除指令(#undef)删除一个已经定义的宏。

  预处理时,编译器将源程序中所有的宏名自动替换回原来的宏文本,称为宏替换宏展开。C++语言中由三种形式的宏,分别为无参宏、有参宏和空宏

  1)无参宏

      #define 宏名 宏文本  //宏名应符合命名规则,习惯上用大写字母命名。宏文本所表示的字符串,可以由任意字符组成,不需要加引号。

  2)有参宏

      #define 宏名(参数列表) 宏文本 //参数列表指定若干可被替换的参数,参数之间通过逗号隔开。

      举例: #define AREA(x)  3.14159 *x*x 若参数是一个表达式还可以写成 #define AREA(x)  3.14159 *(x)*(x) 带上括号优先计算。

  3)空宏

      #define 宏名 //空宏不是用于宏替换,而是配合条件编译指令使用

  4)宏删除

      #undef 宏名

3、条件编译指令

  条件编译指令允许程序员将不同版本的源程序编写在同一程序文件中,便于管理和维护修改。

  1)格式一

      #ifdef 宏名

        代码段1

      #else

        代码段2

      #endif

    编译器在编译代码时、如果宏名已经定义,则编译代码段1,否则编译代码段2.这种格式的条件编译指令一般与空宏搭配使用。如果没有代码段2省略#else

  2)格式二

      #if 常量表达式

        代码段1

      #else

        代码段2

      #endif

    编译器在编译代码时、如果常量表达式的结果为0,则编译代码段1,否则编译代码段2。常量表达式只能包含字面常量或符号常量。如果没有代码段2省略#else

  

  

C++多文件源程序的更多相关文章

  1. vc++ 6.0编译后生成的文件

    程序在编译后,在目标路径下会生成多个文件    Debug文件夹(*.exe,*.ilk,*.obj,*.pch,*.pdb,*.idb,*,pdb),*.cpp,*.dsp,*.ncb,*.plg  ...

  2. vi及缩进设置

    set autoindent,把当前行的对起格式应用到下一行: set smartindent,智能的选择对起方式: set tabstop=4,设置tab键为4个空格: set shiftwidth ...

  3. Matlab与C/C++联合编程之Matlab以MEX方式调用C/C++代码(一)

    MEX文件是一种可在matlab环境中调用的C语言(或fortran)衍生程序,mex的编译结果实际上就是一个带输出函数mexFunction 的dll文件. 中文名 mex文件 外文名 MATLAB ...

  4. vi的用法 【转】

        vi编辑器是所有Unix及Linux系统下标准的编辑器,它的强大不逊色于任何最新的文本编辑器,这里只是简单地介绍一下它的用法和一小部分指令.由于对Unix及Linux系统的任何版本,vi编辑器 ...

  5. 第三次作业随笔(new)包含了补作业

    第三次作业的题目:http://www.cnblogs.com/fzuoop/p/5187275.html 第一次看到题目的时候觉得应该是挺简单的,只要把输入的那一串东西挨个判断,用数列的方法,如果碰 ...

  6. linux 网桥的配置与实现

    ==================================================================================from: http://www.i ...

  7. 关于MEX函数的说明

    reference:http://www.mathworks.com/help/matlab/ref/mex.html .MEX文件是一种可在matlab环境中调用的C(或fortran)语言衍生程序 ...

  8. QBASIC教程

    Qbasic 程序设计入门 BASIC(Beginner’s All-purpose Symbolic Instruction Code 的缩写,意为初学者通用符号指令代码)语言是在1964年由美国的 ...

  9. 单片机开发之C语言编程基本规范

    为了提高源程序的质量和可维护性,从而最终提高软件产品生产力,特编写此规范.本标准规定了程序设计人员进行程序设计时必须遵循的规范.本规范主要针对单片机编程语言和08编译器而言,包括排版.注释.命名.变量 ...

随机推荐

  1. 学习HTTP——HTTPS

    前言 因为工作需要,需要用到大量的关于 HTTP 协议的知识,目前掌握的关于 HTTP 请求以及协议的知识都是零散的,打算针对知识盲区系统的学习一些,理清概念. 为什么会出现 HTTPS 因为 HTT ...

  2. Linux服务器如何识别移动硬盘?

    序言 通常我们使用的移动硬盘或U盘一般都是ntfs或fat32的文件系统,常跟服务器打交道的小伙伴,会经常遇到把移动硬盘或U盘上的数据拷贝到Linux服务器上.绝大多数Linux发行版内核支持fat3 ...

  3. 如何彻底禁止 macOS Monterey 自动更新,去除更新标记和通知

    请访问原文链接:如何彻底禁止 macOS Monterey 自动更新,去除更新标记和通知,查看最新版.原创作品,转载请保留出处. 作者主页:www.sysin.org 随着 macOS Montere ...

  4. 1.Docker简介

    Docker是个什么东西 假定您在开发一个项目,您使用的是一台笔记本电脑而且您的开发环境具有特定的配置.其他开发人员身处的环境配置也各有不同.您正在开发的应用依赖于您当前的配置且还要依赖于某些配置文件 ...

  5. 现有教学数据库JX_DB,作业

    现有教学数据库JX_DB,数据库有以下三个基本表: 学生表student,它由学号sno.姓名sname.性别sex.出生日期Bdate.所在系dept五个属性构成.其中,学号不能为空,值是唯一的: ...

  6. Centons7最小化安装报错:ping: baidu.com: Name or service not know

    在这之前,centos7最小化安装默认是不能联网的,首先必须切换到root用户,再解决网络问题 一.      切换到root用户 二.      解决网络问题  一.切换到root用户 Linux下 ...

  7. KeyDB重量发布6.3.0开源版

    摘要:5月12日 KeyDB 社区隆重发布了 6.3.0开源版本,将与华为加拿大研究院DCS团队2021-2022年合作的成果,深度优化的企业版的能力贡献给了开源社区. KeyDB是目前Redis 分 ...

  8. DEDECMS登录后台,无法连接数据库的原因

    在CMS的网页模块中,当迁移网站出现后台无法登录的时候 最可能的情况有下列几种: 1. 数据库服务器宕机.如果是云上的数据库时,需要联系客服进行解决.是有自己的搭建的数据库,需要查看服务是否正常启动 ...

  9. 【低码】asp.net core 实体类可生产 CRUD 后台管理界面

    前言介绍 喜欢小规模团队的"单打独斗",有的时候即使在大公司,也经常做着3-5个人团队的小项目,相信很多人有类似的经历. 本文介绍如何将项目中已存在的[实体类],直接生产出 CRUD 后台管理界面. ...

  10. 442. Find All Duplicates in an Array - LeetCode

    Question 442. Find All Duplicates in an Array Solution 题目大意:在数据中找重复两次的数 思路:数组排序,前一个与后一个相同的即为要找的数 Jav ...