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

  一个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. Django-ORM-连表正反操作

    一.A表男生,B表女生,C表关系 1通过A表查与某个男生有关系的所有女生 思想1:在A表中确认男生后,通过反查到C表,获取相关内容(QuerySet),然后再跨到B表获取所有女生信息. obj=mod ...

  2. 了解mybatis

    什么是mybatis? MyBatis 是一款优秀的持久层框架,它支持自定义 SQL.存储过程以及高级映射.MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作.MyBati ...

  3. 巧用 Docker 快速部署 GPU 环境

    公众号关注 「开源Linux」 回复「学习」,有我为您特别筛选的学习资料~ 在 Linux 服务器上使用 GPU 跑深度学习的模型很正常不过.如果我们想用 Docker 实现同样的需求,就需要做些额外 ...

  4. 基于Docker&Kubernetes构建PaaS平台基础知识梳理

    点击上方"开源Linux",选择"设为星标" 回复"学习"获取独家整理的学习资料! 基于Docker&Kubernetes构建Paa ...

  5. Centos 7.4_64位系统安装指南

    小土豆Linux学习随笔 -- 清听凌雪慕忆 目录 1. 范围 1.1标识 1.2 文档概述 2. 安装环境 3. 安装步骤 4. 注意事项 1. 范围 1.1标识 CentOS 7.4 64位系统安 ...

  6. Docker的基本原理及使用

    Docker 安装 https://docs.docker.com/engine/install/ubuntu/ 应用场景 Web 应用的自动化打包和发布. 自动化测试和持续集成.发布. 在服务型环境 ...

  7. mysqldump还原备份数据时遇到一个问题

    问题描述 ERROR 1839 (HY000) at line 24: @@GLOBAL.GTID_PURGED can only be set when @@GLOBAL.GTID_MODE = O ...

  8. 一文带你搞懂 Kafka 的系统架构(深度好文,值得收藏)

    Kafka 简介 Kafka 是一种高吞吐.分布式.基于发布和订阅模型的消息系统,最初是由 LinkedIn 公司采用 Scala 和 java 开发的开源流处理软件平台,目前是 Apache 的开源 ...

  9. Android——RelativeLayout

    代码:<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android= ...

  10. Elasticsearch(es)介绍与安装

    ### RabbitMQ从入门到集群架构: https://zhuanlan.zhihu.com/p/375157411 可靠性高 ### Kafka从入门到精通: https://zhuanlan. ...