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

  一个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. Vue图片浏览组件v-viewer使用

    简单介绍v-viewer的两种使用方法: Demo 安装依赖: npm install v-viewer --save 全局引入 import Viewer from 'v-viewer' impor ...

  2. Linux screen命令详解

    开源Linux 长按二维码加关注~ 上一篇:局域网IP冲突罪魁祸首是谁? 很多时候,我们都需要执行一些需要很长时间的任务.如果这时候,你的网络连接突然断开了,那么你之前所做的所有工作可能都会丢失,所做 ...

  3. java高级用法之:JNA中的Memory和Pointer

    目录 简介 Pointer 特殊的Pointer:Opaque Memory 总结 简介 我们知道在native的代码中有很多指针,这些指针在JNA中被映射成为Pointer.除了Pointer之外, ...

  4. XPath语法和lxml模块

    XPath语法和lxml模块 什么是XPath? xpath(XML Path Language)是一门在XML和HTML文档中查找信息的语言,可用来在XML和HTML文档中对元素和属性进行遍历. X ...

  5. 2. 假设当前文件夹中data.csv文件中存放了2020年某饭店营业额,第一列为日期(如2020-02-03),第二列为每天交易额(如3560),文件中第一行为表头,其余行为实 际数据。

    假设当前文件夹中data.csv文件中存放了2020年某饭店营业额,第一列为日期(如2020-02-03),第二列为每天交易额(如3560),文件中第一行为表头,其余行为实  际数据.编写程序,完成下 ...

  6. OAuth2授权服务器Id Server一键生成配置原理

    OAuth2客户端的配置参数非常多,虽然Id Server通过控制台可视化解决了创建OAuth2客户端的问题.但是如何进一步降低OAuth2的使用难度,把创建的OAuth2客户端转化为配置成为了刚需, ...

  7. 四、针对redis容灾切换导致"脑裂"的情况

    网上参考到别人博客说,redis容灾切换的时候,有几率出现脑裂的情况. 什么是脑裂: sentinel判断master宕机,切换slave为新master的过程中,业务数据还在持续往原master写入 ...

  8. Kubernetes client-go DeltaFIFO 源码分析

    概述Queue 接口DeltaFIFO元素增删改 - queueActionLocked()Pop()Replace() 概述 源码版本信息 Project: kubernetes Branch: m ...

  9. Spring中的Bean作用域

    概述 scope用来声明容器中的对象所应该处的限定场景或者说该对象的存活时间,即容器在对象进入其 相应的scope之前,生成并装配这些对象,在该对象不再处于这些scope的限定之后,容器通常会销毁这些 ...

  10. 一个支持数据绑定与数据联动的Dashboard

    什么是仪表盘 仪表盘是不同部件的组合,可以在一个页面集中显示各类信息,方便用户集中查看信息.并快速处理业务 关于制作部件,请参见:制作部件 CabloyJS仪表盘的特点 更灵活的自适应能力,可以针对m ...