




已阅读5页,还剩6页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
精品文档C+多文件程序多文件结构和编译预处理命令一.C+程序的多文件结构一个程序按结构至少可以划分为三个文件:类的声明文件(*.h文件)、类的实现文件(*.cpp文件)和主函数文件(使用到类的文件,*.cpp文件),如果程序更复杂,我们会为每个类单独建一个声明文件和一个实现文件。这样我们要修改某个类时就直接找到它的文件修改即可,不需要其他的文件改动。时钟类的例子:/ 文件1:Clock类的声明,可以起名为Clock.h#include using namespace std;class Clock /时钟类声明public: /外部接口 Clock(); void SetTime(int NewH, int NewM, int NewS); /三个形参均具有函数原型作用域 void ShowTime(); Clock() private: /私有数据成员 int Hour,Minute,Second;/ 文件2:Clock类的实现,可以起名为Clock.cpp#include Clock.h/时钟类成员函数实现Clock:Clock() /构造函数 Hour=0; Minute=0; Second=0;void Clock:SetTime(int NewH,int NewM,int NewS) Hour=NewH; Minute=NewM; Second=NewS;void Clock:ShowTime() coutHour:Minute:Secondendl;/ 文件3:主函数,可以起名为main.cpp#include Clock.h/声明全局对象g_Clock,具有文件作用域,静态生存期Clock g_Clock;int main() /主函数 cout文件作用域的时钟类对象:endl; /引用具有文件作用域的对象: g_Clock.ShowTime(); g_Clock.SetTime(10,20,30); Clock myClock(g_Clock); /声明具有块作用域的对象myClock,并通过默认拷贝构造函数用g_Clock初始化myClock cout块作用域的时钟类对象:Add Class,在弹出的对话框中选择c+ class,然后由弹出个对话框,在class name处填上类名点finish就可以了,这样.h文件和.cpp文件会自动生成,我们也可以点Project-Add New Item,在弹出的对话框中选择Header File(.h)或C+ File(.cpp)来生成.h文件或.cpp文件。二.编译预处理程序编译器在编译源程序以前,要由预处理程序对源程序文件进行预处理。预处理程序提供了一些编译预处理指令和预处理操作符。预处理指令都要由“#”开头,每个预处理指令必须单独占一行,而且不能用分号结束,可以出现在程序文件中的任何位置。1.#include指令#include指令也叫文件包含指令,用来将另一个源文件的内容嵌入到当前源文件该点处。其实我们一般就用此指令来包含头文件。#include指令有两种写法:#include 使用这种写法时,会在C+安装目录的include子目录下寻找中标明的文件,通常叫做按标准方式搜索。#include 文件名使用这种写法时,会先在当前目录也就是当前工程的目录中寻找中标明的文件,若没有找到,则按标准方式搜索。2.#define和#undef指令如果你学过C语言,就会知道用#define可以定义符号常量,比如,#define PI 3.14 这条指令定义了一个符号常量PI,它的值是3.14。C+也可以这样定义符号常量,但一般更常用的是在声明时用const关键字修饰。C语言还用#define定义参数宏,来实现简单的函数运算,比如,#define add(x,y) (x+y) 这条指令说明如果我们用到add(1,2)则预处理后就会用(1+2)代替,C+中一般用内联函数来实现。#undef用来删除由#define定义的宏,使其不再起作用。3.条件编译指令用条件编译指令可以实现某些代码在满足一定条件时才会参与编译,这样我们可以利用条件编译指令将同一个程序在不同的编译条件下生成不同的目标代码。例如,我们可以在调试程序时加入一些调试语句,用条件编译指令控制只有在debug模式下这些调试语句才参与编译,而在release模式下不参与编译。条件编译指令有5中形式:a.第一种形式:#if 常量表达式 程序正文 /当“ 常量表达式”非零时本程序段参与编译#endifb.第二种形式:#if 常量表达式 程序正文1/当“ 常量表达式”非零时本程序段参与编译#else 程序正文2/当“ 常量表达式”为零时本程序段参与编译#endifc.第三种形式:#if 常量表达式1 程序正文1 /当“ 常量表达式1”非零时本程序段参与编译elif 常量表达式2 程序正文2 /当“常量表达式1”为零、“ 常量表达式2”非零时本程序段参与编译 .elif 常量表达式n 程序正文n /当“常量表达式1”、.、“常量表达式n-1”均为零、“ 常量表达式n”非零时本程序段参与编译#else 程序正文n+1 /其他情况下本程序段参与编译#endifd.第四种形式:#ifdef 标识符 程序段1#else 程序段2#endif如果“标识符”经#defined定义过,且未经undef删除,则编译程序段1,否则编译程序段2。e.第五种形式:#ifndef 标识符 程序段1#else 程序段2#endif如果“标识符”未被定义过,则编译程序段1,否则编译程序段2。4.define操作符define是预处理操作符,不是指令,所以不能用#开头。使用形式为:define(标识符)。如果括号里的标识符用#define定义过,并且没有用#undef删除,则define(标识符)为非0,否则为0。可以这样使用: #if !define(HEAD_H) #define HEAD_H我们在包含头文件时,有时多次重复包含同一个头文件,比如下面这种情况: / main.cpp文件#include file1.h#include file2.hint main()/ file1.h文件#include head.h / file2.h文件#include head.h / head.h文件 .class A.main.cpp包含了file1.h文件,file1.h又包含了head.h文件,main.cpp还包含了file2.h文件,file2.h也包含了head.h文件,那么main.cpp就包含了两次head.h文件,在编译时就会报错,说head.h中的类A重复定义了。这时我们可以在被重复包含的文件head.h中使用条件编译指令,用一个唯一的标识符来标识head.h文件是否已经编译过,如果已经编译过则不会重复编译了。鸡啄米给大家改写下上面的head.h文件:/ head.h文件#ifndef HEAD_H#define HEAD_H.class A .#endif在这个改好的head.h文件中,上来会先判断HEAD_H是否被定义过,如果没有被定义过,则head.h文件还没参与过编译,就编译此文件中的源代码,同时定义HEAD_H,标记head.h文件已经参与过编译。如果HEAD_H已经被定义过,则说明此文件已经参与过编译,编译器会跳过本文件左右内容编译其他部分,类A也不会有重复定义的错误了。-C语言的要求:函数先声明后定义-example 1: test1.c中#includeint main(void) printf(%dn,fun(5);int fun()printf(Hello Worldn);/代码编译,链接都能够通过。但是会有警告:warning C4013: fun undefined; assuming extern returning intwarning C4716: fun : must return a value通过可以看出虽然fun(5)在使用前没有声明,但是编译器仅仅是给出警告,并提供默认的函数声明类型:int name(void); (参考C语言创始人的书),编译器在遇到 fun(5) 的“fun(”的时候就假设fun是一个函数,如果没有找到fun函数,就提供默认的函数声明,且忽略fun中的函数参数。并在链接的过程中找到了fun函数的定义,则通过链接,生成可执行代码。如下代码,能够通过编译,却不能通过链接,因为链接的时候找不到fun函数的定义。#includeint main(void)printf(%dn,fun(5);-注:第一个程序在C+编译器里不能通过编译,因为C+编译器严格要求函数先声明后使用,如果找不到声明,不能通过编译,编译器并不会提供默认的函数声明。-多文件组织中函数的先声明后定义-test1.c#includeint main(void)printf(%dn,fun(5);-test2.cint fun()printf(Hello Worldn);-上述文件在编译时能够通过编译,并且能偶通过链接,但是会产生如下警告:Test1.c : warning C4013: fun undefined; assuming extern returning intTest2.c:warning C4013: printf undefined; assuming extern returning intwarning C4716: fun : must return a valuetest1.c中产生警告的原因是上面已经解释过了,链接能够通过是链接器能够自动的把一起编译的test1.c和test2.c中可执行代码链接起来,这样test1.c中的fun函数就找到了定义。Test2.c中第一个警告是由于上述同样的原因,能够通过链接是由于test1.c中已经包含了头文件,把printf的可执行代码给链接过来了,所以test2.c中的printf也就能够找到定义。-上述例子说明多个源文件文件在编译环境下可以通过链接器自动连接到一起并不需要头文件的参与,但是为了程序的可移植性和正确性,一定要遵循先声明后使用的原则:这个原则不但适用于函数,也使用全局变量。-头文件中应该包含什么-test.hint a;void show(void)printf(Hello worldn);-test1.cint fun()printf(Hello Worldn);-test2.c#include#include test.hint main(void)printf(%dn,fun(5);上述编译和链接同样能够通过,通过上面的例子不难理解:因为就是在头文件中定义了全局变量,并把它包含在test2.c中;-test.hint a;void show(void)printf(Hello worldn);-test1.c#include “test.h ”int fun()printf(Hello Worldn);-test2.c#include#include test.hint main(void)printf(%dn,fun(5);-上述多文件程序能够通过编译,却不能通过链接:error LNK2005: _show already defined in test1.objfatal error LNK1169: one or more multiply defined symbols found具体原因有以下两个:1:test1.c包含了test.h的头文件,定义了全局变量 a,同理test.2也通过相同的手段定义了全局变量a;2: test1.c和test2.c通过上述手段分别提供了show的定义-上述分析指出在链接的过程中由于出现了同一个函数和变量的多个定义,所以链接出错。所以在头文件不要包含函数的定义和全局变量的定义,这样做虽然有时候链接和编译都能通过,但是还是有一定的隐患。 总结,在头文件中一般只包含函数的声明和全局变量的声明。函数的声明大家都知道,全局变量的声明大家不一定清楚:必须显式的提供extern如:extern int a; 注意在头文件中这样只是声明,并不提供实际的定义,在使用该变量的源文件中还有重新以 int a ; 的形式重新定义,而其他使用该全局变量的源文件只需包含该头文件即可。C+ 多个头文件的编译技巧介绍2010-11-01 00:00中国IT实验室佚名关键字:C+ 编译 头文件 企业软件热点文章 Java多线程实现异步调用 为Oracle导出文件加上时间戳 1,文件 .CPP里包含的头文件要正确.改包含的要包含。2,main函数里要包含你编写全部.H头文件。3,如没问题参照以下步骤。举个例子吧:假设你已经编写好了以下3个文件(或者更多):SSList.H 头文件SSList.cpp (函数)实现文件 (后缀为.c也可以)SSList_main.cpp 主(调用)文件 (后缀为.c也可以)并将它们放在
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 航海船舶能源管理方案
- 货物运输合同签订中的知识产权保护与侵权责任
- 风险投资机构股权转让及项目孵化合作协议
- 商业空间租赁合同转让与经营许可三方协议
- 音乐培训机构兼职教师聘用及教学成果转化协议
- 离婚纠纷调解协议履行及子女监护权争议解决执行书
- 2025年耳鼻喉科影像学诊断试题答案及解析
- 离婚财产分割协议范本:婚前婚后财产权益保障
- 生态园区物业充电桩场地租赁合同范本
- 基于子女抚养与财产分配的离婚协议起草模板
- GB/T 23902-2021无损检测超声检测超声衍射声时技术检测和评价方法
- 邀请函模板完整
- 2020新译林版高中英语选择性必修二全册课文及翻译(英汉对照)
- 大学物理第14章光的衍射课件
- 家长会 课件(共44张ppt) 九年级上学期
- 钻孔灌注桩施工安全控制培训教材课件
- 福建省莆田市各县区乡镇行政村村庄村名明细
- 大班幼儿随访电访记录表内有内容
- 干细胞精品课件
- 太阳能路灯说明书完整版
- 中国老龄化社会的潜藏价值(中英)
评论
0/150
提交评论