C++多文件源程序
一、多文件结构的源代码组织
一个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++多文件源程序的更多相关文章
- vc++ 6.0编译后生成的文件
程序在编译后,在目标路径下会生成多个文件 Debug文件夹(*.exe,*.ilk,*.obj,*.pch,*.pdb,*.idb,*,pdb),*.cpp,*.dsp,*.ncb,*.plg ...
- vi及缩进设置
set autoindent,把当前行的对起格式应用到下一行: set smartindent,智能的选择对起方式: set tabstop=4,设置tab键为4个空格: set shiftwidth ...
- Matlab与C/C++联合编程之Matlab以MEX方式调用C/C++代码(一)
MEX文件是一种可在matlab环境中调用的C语言(或fortran)衍生程序,mex的编译结果实际上就是一个带输出函数mexFunction 的dll文件. 中文名 mex文件 外文名 MATLAB ...
- vi的用法 【转】
vi编辑器是所有Unix及Linux系统下标准的编辑器,它的强大不逊色于任何最新的文本编辑器,这里只是简单地介绍一下它的用法和一小部分指令.由于对Unix及Linux系统的任何版本,vi编辑器 ...
- 第三次作业随笔(new)包含了补作业
第三次作业的题目:http://www.cnblogs.com/fzuoop/p/5187275.html 第一次看到题目的时候觉得应该是挺简单的,只要把输入的那一串东西挨个判断,用数列的方法,如果碰 ...
- linux 网桥的配置与实现
==================================================================================from: http://www.i ...
- 关于MEX函数的说明
reference:http://www.mathworks.com/help/matlab/ref/mex.html .MEX文件是一种可在matlab环境中调用的C(或fortran)语言衍生程序 ...
- QBASIC教程
Qbasic 程序设计入门 BASIC(Beginner’s All-purpose Symbolic Instruction Code 的缩写,意为初学者通用符号指令代码)语言是在1964年由美国的 ...
- 单片机开发之C语言编程基本规范
为了提高源程序的质量和可维护性,从而最终提高软件产品生产力,特编写此规范.本标准规定了程序设计人员进行程序设计时必须遵循的规范.本规范主要针对单片机编程语言和08编译器而言,包括排版.注释.命名.变量 ...
随机推荐
- 如何突破Jenkins瓶颈,实现集中管理、灵活高效的CI/CD
在过去的几年间,随着DevOps的兴起,持续集成(Continuous Integration)与持续交付(Continuous Delivery)的热度也水涨船高.在本文中,我们将首先带您了解热门的 ...
- 【论文笔记】A review of applications in federated learning(综述)
A review of applications in federated learning Authors Li Li, Yuxi Fan, Mike Tse, Kuo-Yi Lin Keyword ...
- vmware ubuntu 忘记密码
1.进入recovery模式 修改root密码 1.启动ubuntu系统,一开始在有进度条的时候按下shift键,出现GRUB选择菜单,选择Advanced options for Ubuntu 按回 ...
- CentOS开机流程详解
一个执着于技术的公众号 开机流程 BIOS: (Basic Input Output System)基本输入输出系统,它是一组固化到计算机内主板上一个ROM芯片上的程序,保存着计算机最重要的基本输入输 ...
- TCP 协议有哪些缺陷?
作者:小林coding 图解计算机基础网站:https://xiaolincoding.com 大家好,我是小林. 忽然思考一个问题,TCP 通过序列号.确认应答.超时重传.流量控制.拥塞控制等方式实 ...
- 98. 验证二叉搜索树 前序遍历解法以及后续遍历解法(go语言)
leetcode题目 98. 验证二叉搜索树 前序遍历 最简洁的答案版本,由于先判断的是根节点,所以直接判断当前root的值v,是否满足大于左子树最大,小于右子树最小,然后再遍历左子树,右子树是否是这 ...
- DirectX11--CPU与GPU计时器
前言 GAMES104的王希说过: 游戏引擎的世界里,它的核心是靠Tick()函数把这个世界驱动起来. 本来单是一个CPU的计时器是不至于为其写一篇博客的,但把GPU计时器功能加上后就不一样了.在这一 ...
- Git标签用法
我们通常会在项目开发到一定阶段时给代码打上标签. 1.Git查看所有标签及其描述信息 git tag -l -n 2.Git创建标签 创建标签并添加描述信息 git tag -a v1.0.0 -m ...
- 印尼医疗龙头企业Halodoc的数据平台转型之Lakehouse架构
1. 摘要 在 Halodoc,我们始终致力于为最终用户简化医疗保健服务,随着公司的发展,我们不断构建和提供新功能. 我们两年前建立的可能无法支持我们今天管理的数据量,以解决我们决定改进数据平台架构的 ...
- 【Java面试】Spring中 BeanFactory和FactoryBean的区别
一个工作了六年多的粉丝,胸有成竹的去京东面试. 然后被Spring里面的一个问题卡住,唉,我和他说,6年啦,Spring都没搞明白? 那怎么去让面试官给你通过呢? 这个问题是: Spring中Bean ...