已阅读5页,还剩115页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
第5章数据的共享与保护 第5章数据的共享与保护 1 标识符的作用域与可见性2 对象的生存期3 类的静态成员 微视频 4 类的友元5 共享数据的保护 微视频 6 多文件结构和编译预处理命令 微视频 7 综合实例 个人银行账户管理程序 微视频 8 小结 第5章数据的共享与保护 1 标识符的作用域与可见性2 对象的生存期3 类的静态成员 微视频 4 类的友元5 共享数据的保护 微视频 6 多文件结构和编译预处理命令 微视频 7 综合实例 个人银行账户管理程序 微视频 8 小结 1 标识符的作用域与可见性 作用域可见性 作用域 作用域是一个标识符在程序正文中有效的区域 C 中标识符的作用域 1 函数原型作用域2 局部作用域 块作用域 3 类作用域4 命名空间作用域 文件作用域 1 函数原型作用域 函数原型中的参数 其作用域始于 结束于 例如 设有下列原型声明 doubleArea doubleradius 2 局部作用域 块作用域 在块中声明的标识符 其作用域自声明处起 限于块中 例如 voidfun inta intb a cin b if b 0 intc a的作用域在哪儿 3 类作用域 类作用域作用于特定的成员名 类X的成员m具有类作用域 对m的访问方式如下 如果在X的成员函数中没有声明同名的局部作用域标识符 那么在该函数内可以访问成员m 属于类内访问 通过表达式x m或者X m访问 属于类外访问 通过表达式prt m访问 其中prt为指向X类的一个对象的指针 属于类外访问 4 命名空间作用域 文件作用域 一个大型的程序通常由不同模块构成 不同的模块甚至有可能是由不同人员开发的 不同模块中的类和函数之间可能发生重名 这样就会引发错误 命名空间 namespace 的概念正是为了解决这个问题而提出的 一个命名空间将不同的标识符集合在一个命名作用域 namedscope 内 这样 在不同的命名空间中 即使使用同样的标识符来表示不同的事物 也不会引起命名冲突 4 命名空间作用域 文件作用域 命名空间的语法形式如下 namespace命名空间名 命名空间内的各种声明 函数声明 类声明等 在命名空间内部可以直接引用当前命名空间中声明的标识符 如果需要引用其他命名空间的标识符 需要使用以下语法 命名空间名 标识符名 4 命名空间作用域 文件作用域 includenamespacemycode voidsqrt intmain mycode sqrt return0 namespacemycode voidsqrt std cout sqrtcalledinthemycodenamespace std endl 运行结果 sqrtcalledinthemycodenamespace 4 命名空间作用域 文件作用域 在标识符前总使用命名空间限定 会显得过于冗长 C 为此提供了using语句的两种形式 using命名空间名 标识符名 usingnamespace命名空间名 第1种形式将命名空间内的某一指定标识符暴露在当前的作用域内 使得在当前作用域中可以直接引用这个指定的标识符 第2种形式将命名空间内的所有标识符暴露在当前的作用域内 使得在当前作用域中可以直接引用命名空间内的所有 任何 标识符 4 命名空间作用域 文件作用域 includenamespacemycode voidsqrt std cout sqrtcalledinthemycodenamespace std endl usingnamespacemycode intmain sqrt return0 运行结果 sqrtcalledinthemycodenamespace 4 命名空间作用域 文件作用域 C 标准程序库的所有标识符都被声明在std命名空间内 所以 如果前面的程序使用了usingnamespacestd 那么可以直接使用cin cout endl等标识符 如果前面的程序没有使用usingnamespacestd 那么只能这样使用std cin std cout std endl等标识符 例5 1作用域实例 运行结果 i 7j 6i 5 includeusingnamespacestd inti 在全局命名空间中的全局变量namespaceNs intj 在Ns命名空间中的全局变量intmain i 5 为全局变量i赋值Ns j 6 为全局变量j赋值 usingnamespaceNs 子块inti 局部变量 局部作用域i 7 为局部变量i赋值cout i i endl 输出7cout j j endl 输出6 cout i i endl 输出5return0 可见性 可见性是从对标识符的引用的角度来看标识符的有效范围 可见性表示从内层作用域向外层作用域 看 时能看见什么 如果标识符在某处可见 则就可以在该处引用此标识符 可见性 作用域可见性的一般规则 标识符应声明在先 引用在后 在同一作用域中 不能声明同名的标识符 在没有互相包含关系的不同的作用域中声明的同名标识符 互不影响 如果某个标识符在外层中声明 且在内层中没有同一标识符的声明 则该标识符在内层可见 如果在两个或多个具有包含关系的作用域中声明了同名标识符 则外层标识符在内层不可见 同一作用域中的同名标识符 在同一作用域内的对象名 函数名 枚举常量名会隐藏同名的类名或枚举类型名 ClockClock Clock setTime 重载的函数可以有相同的函数名 作用域和可见性的原则不仅适用于变量名 而且也同样适用于其他各种标识符 包括常量名 用户自定义的类型名 函数名 枚举类型的取值等 第5章数据的共享与保护 1 标识符的作用域与可见性2 对象的生存期3 类的静态成员 微视频 4 类的友元5 共享数据的保护 微视频 6 多文件结构和编译预处理命令 微视频 7 综合实例 个人银行账户管理程序 微视频 8 小结 2 对象的生存期 对象 包括简单变量 从产生到结束的这段时间就是它的生存期 在对象生存期内 对象 包括简单变量 将保持它的状态 即 数据成员的值 直到它们被更新为止 对象的生存期分为 静态生存期动态生存期 静态生存期 如果对象生存期与程序的运行期相同 则称它具有静态生存期 在命名空间作用域中声明的对象具有这种静态生存期 在函数内部声明静态生存期对象 要冠以关键字static 例 静态生存期 运行结果 i 523 includeusingnamespacestd inti 5 命名空间作用域 i具有静态生存期voidprint staticintj 1 静态局部变量j具有静态生存期j cout j endl intmain cout i i endl print print return0 动态生存期 块作用域中声明的 没有用static修饰的对象是动态生存期的对象 习惯称局部生存期对象 局部生存期对象诞生于声明点时 结束于声明所在的块执行完毕时 例 动态生存期 运行结果 i 6 a 2i 6 a 3 includeusingnamespacestd voidfun intmain fun fun return0 voidfun staticinta 1 a是静态生存期inti 5 i是动态生存期a i cout i i a a endl 例5 2变量的生存期与可见性 includeusingnamespacestd inti 1 i为全局变量 具有静态生存期voidother void staticinta 2 a b为静态局部变量 具有全局寿命 局部可见 staticintb 只在第一次进入函数时被初始化intc 10 c为局部变量 具有动态生存期 每次进入函数时都初始化a 2 i 32 c 5 cout OTHER endl cout i i a a b b c c endl b a intmain staticinta a为静态局部变量 具有全局寿命 局部可见 b c为局部变量 具有动态生存期intb 10 intc 0 cout MAIN endl cout i i a a b b c c endl c 8 other cout MAIN endl cout i i a a b b c c endl i 10 other return0 运行结果 MAIN i 1a 0b 10c 0 OTHER i 33a 4b 0c 15 MAIN i 33a 0b 10c 8 OTHER i 75a 6b 4c 15 例5 2 例5 3 includeusingnamespacestd classClock 时钟类定义public 外部接口Clock voidsetTime intNewH intNewM intNewS 3个形参均具有函数原型作用域voidshowTime private 私有数据成员inthour minute second 例5 3具有静态和动态生存期对象的时钟程序 时钟类成员函数实现Clock Clock hour 0 minute 0 second 0 默认构造函数voidClock setTime intNewH intNewM intNewS 3个形参均具有局部作用域hour NewH minute NewM second NewS voidClock showTime cout hour minute second endl 例5 3 ClockglobClock 声明全局对象globClock 具有静态生存期 命名空间作用域 文件作用域 由默认构造函数初始化为0 0 0intmain 主函数cout Thefirsttimeoutput endl 引用具有命名空间作用域 文件作用域 的对象globClock 对象的成员函数具有类作用域 显示0 0 0globClock showTime globClock setTime 8 30 30 将时间设置为8 30 30ClockmyClock globClock 声明具有块作用域的对象myClockcout Thesecondtimeoutput endl myClock showTime 引用具有块作用域的对象myClockreturn0 运行结果 Thefirsttimeoutput 0 0 0Thesecondtimeoutput 8 30 30 例5 3 第5章数据的共享与保护 1 标识符的作用域与可见性2 对象的生存期3 类的静态成员 微视频 4 类的友元5 共享数据的保护 微视频 6 多文件结构和编译预处理命令 微视频 7 综合实例 个人银行账户管理程序 微视频 8 小结 3 类的静态成员 在结构化程序设计中 程序模块的基本单位是函数 因此模块间对内存中数据的共享是通过函数与函数之间的数据共享来实现的 其中包括两个途径 参数传递和全局变量 数据存储在局部对象中 通过参数传递实现共享 函数间的参数传递 数据存储在全局对象中 使用全局对象 includeintglobal voidf global 5 voidg cout global endl intmain f g 输出 5 return0 将函数与数据封装 includeusingnamespacestd classApplication public voidf voidg private intglobal voidApplication f global 5 voidApplication g cout global endl intmain ApplicationMyApp MyApp f MyApp g return0 3 类的静态成员 面向对象的程序设计方法兼顾数据的共享与保护 将数据与操作数据的函数封装在一起 构成集成度更高的模块 类中的数据成员可以被同一类中的任何一个函数访问 这样一方面在类内部的函数之间实现了数据共享 另一方面这种共享是受限制的 可以设置适当的访问控制属性 把共享只限制在类的范围之内 对类外来说 类的数据成员仍然是隐藏的 达到了共享与隐藏 3 类的静态成员 在数据共享方面 除了 函数之间的数据共享 参数传递和全局变量类内部的函数之间实现了数据共享之外 对象与对象之间也需要共享数据 静态成员能解决同一个类的不同对象之间数据和函数共享的问题 3 类的静态成员 例 classEmployee private intempNo intid stringname 字符串对象 如果需要统计雇员总数 这个数据存放在哪里 3 类的静态成员 例 classEmployee Private intempNo intid stringname 字符串对象staticintcount count这个数据成员是静态数据成员 表示总数 3 类的静态成员 如果以类外的变量来存储总数 则不能实现数据的隐藏 如果在类中增加一个数据成员用于存放总数 必然在每一个对象中都存储一个副本 这样不仅使数据冗余 而且每个对象分别维护一个 总数 容易形成维护对象的成本太高 并且极易造成数据的不一致 由于这个总数应该是为Employee类的所有对象所共享 因此比较理想的方案是类的所有对象共同拥有一个存放总数的数据成员 静态数据成员 3 类的静态成员 静态数据成员静态成员函数 静态数据成员 count这个静态数据成员具有 类属性 表明这个属性不属于任何一个具体对象 而是为整个类所共有 或者说 为每个对象所共有 静态成员在每个类只有一个副本 而不是在每一个对象中都存储一个副本 静态成员由该类的所有对象共同维护和使用 从而实现了同一类的不同对象之间的数据共享 类属性是描述类的所有对象共同特征的一个数据项 对于任何对象实例 它的属性值是相同的 静态数据成员 静态数据成员用关键字static声明 该类的所有对象维护该成员的同一个拷贝 必须在类外定义和初始化 用作用域运算符 来指明所属的类 静态成员函数类外代码可以使用类名和作用域运算符 来调用静态成员函数 静态成员函数只能引用属于该类的静态数据成员或静态成员函数 例5 4具有静态数据成员的Point类 classPoint Point类定义public 外部接口Point intxx 0 intyy 0 x xx y yy 构造函数count 在构造函数中对count累加 所有对象共同维护同一个countPoint Point intPoint count 0 静态数据成员定义和初始化 使用类名限定intmain 主函数 Pointa 4 5 定义对象a 其构造函数会使count增1cout PointA a getX a getY a showCount 输出对象个数Pointb a 定义对象b 其复制构造函数会使count增1cout PointB b getX b getY b showCount 输出对象个数cout PointA a getX a getY a showCount 输出对象个数cout ThesizeofPoint sizeof Point endl 输出8 而不是12return0 运行结果 PointA 4 5Objectcount 1PointB 4 5Objectcount 2PointA 4 5Objectcount 2ThesizeofPoint 8 例5 4 静态数据成员 在前面的例子中 类Point的数据成员count被声明为静态 static 用来给Point类的对象计数 每定义一个新对象 count的值就相应加1 静态数据成员count的定义和初始化在类外进行 首先要利用类名来引用 intPoint count 0 其次 虽然这个静态数据成员是私有类型 在这里却可以直接初始化 除此之外 在类外就不允许直接访问了 在所有对象声明之前count的值是初始值0 如何输出这个初始值呢 静态成员函数 类的静态成员函数是专门用来输出静态成员的 要输出静态成员 可以通过类的某个对象来调用静态成员函数 更可以 更推荐 通过类名来调用静态成员函数 而非静态成员函数只能通过对象名来调用 然而 通过静态成员函数访问非静态成员是相当麻烦的 通常 静态成员函数只用来访问同一个类中的静态数据成员 维护对象之间共享的数据 例5 5具有静态数据和函数成员的Point类 classPoint Point类定义public 外部接口Point intxx 0 intyy 0 x xx y yy 构造函数count 在构造函数中对count累加 所有对象共同维护同一个countPoint Point intPoint count 0 静态数据成员定义和初始化 使用类名限定intmain 主函数 Point showCount 输出对象个数Pointa 4 5 定义对象a 其构造函数会使count增1cout PointA a getX a getY Point showCount 输出对象个数Pointb a 定义对象b 其复制构造函数会使count增1cout PointB b getX b getY Point showCount 输出对象个数a showCount b showCount return0 运行结果 Objectcount 0PointA 4 5Objectcount 1PointB 4 5Objectcount 2Objectcount 2Objectcount 2 例5 5 例5 4与例5 5的比较 采用静态成员函数的好处是可以不依赖于任何对象 直接访问静态数据 静态成员函数适于访问静态数据成员 静态成员函数可以直接访问该类的静态数据成员和成员函数 而静态成员函数若要访问非静态成员 则必须通过对象名 因此 静态成员函数不适于访问非静态成员 classA public staticvoidf Aa private intx voidA f Aa cout x 对x的引用是错误的cout a x 正确 第5章数据的共享与保护 1 标识符的作用域与可见性2 对象的生存期3 类的静态成员 微视频 4 类的友元5 共享数据的保护 微视频 6 多文件结构和编译预处理命令 微视频 7 综合实例 个人银行账户管理程序 微视频 8 小结 4 类的友元 友元是C 提供的一种破坏数据封装和数据隐藏的机制 通过将一个模块声明为另一个模块的友元 一个模块能够引用到另一个模块中本是被隐藏的信息 可以使用友元函数和友元类 为了确保数据的完整性 及数据封装与隐藏的原则 建议尽量不使用或少使用友元 类B的函数能否直接访问类A的私有成员 classA public voiddisplay cout x endl intgetX returnx private intx classB public voidset inti a x i 错误voiddisplay private Aa 如果类B的成员函数是类A的友元函数 则上述set函数中的 a x i 语句就是正确的 友元关系 友元关系提供了不同类或对象的成员函数之间 类的成员函数与一般函数之间进行数据共享的机制 友元关系就是一个类主动声明哪些其他类或函数是它的朋友 进而给它们提供对本类的访问特许 通过友元关系 一个普通函数或者类的成员函数可以访问封装于另外一个类中的数据 友元关系 从一定程度讲 友元是对数据隐蔽和封装的破坏 但是为了数据共享 提高程序的效率和可读性 在很多情况下 这种小的破坏也是必要的 关键是度的问题 在一个类中 可以利用关键字friend将其他函数或类声明为友元 如果友元是一般函数或成员函数 称为友元函数 如果友元是一个类 则称为友元类 友元类的所有成员都自动成为友元函数 4 类的友元 友元函数友元类 友元函数 友元函数是在类声明中由关键字friend修饰说明的非成员函数 在它的函数体中能够通过对象名访问private和protected成员 作用 增加灵活性 使程序员可以在封装和快速性方面做合理选择 访问对象中的成员必须通过对象名 例5 6使用友元函数计算两点间的距离 include includeusingnamespacestd classPoint Point类定义public 外部接口Point intxx 0 intyy 0 x xx y yy intgetX returnx intgetY returny friendfloatdist Point floatdist Point 运行结果 Thedistanceis 5 例5 6 使用友元与使用类的组合的比较 对于计算任意两点间距离这个问题来说 使用友元可以使程序具有更好的可读性 如果是要表示线段 则使用Line类更为恰当 对于同一个问题 虽然从语法上可以有多个解决方案 但应该根据问题的实质去选择一种能够比较直接地反映问题域本来面目的方案 友元类 若一个类为另一个类的友元 则此类的所有成员都能访问对方类的私有成员 声明语法 将友元类名在另一个类中使用friend修饰说明 友元类举例 classA friendclassB public voidDisplay cout x endl private intx classB public voidSet inti voidDisplay private Aa voidB Set inti a x i voidB Display a Display 友元关系是不能传递的 B类是A类的友元 C类是B类的友元 C类与A类之间 如果没有声明 就没有任何友元关系 友元关系是单向的 如果声明B类是A类的友元 B类的成员函数就可以访问A类的私有和保护数据 但A类的成员函数却不能访问B类的私有 保护数据 友元关系是不被继承的 如果类B是类A的友元 类B的派生类并不会自动成为类A的友元 这就如同 别人信任你 但是不见得也信任你的孩子 第5章数据的共享与保护 1 标识符的作用域与可见性2 对象的生存期3 类的静态成员 微视频 4 类的友元5 共享数据的保护 微视频 6 多文件结构和编译预处理命令 微视频 7 综合实例 个人银行账户管理程序 微视频 8 小结 5 共享数据的保护 虽然数据隐藏保证了数据的安全性 但是各种形式的数据共享却又不同程度地破坏了数据的安全性 因此 对于既需要共享又需要防止改变的数据 应该将其声明为常量 因为常量在程序运行期间是不可以改变的 所以可以有效地保护数据 常类型 常类型的对象必须进行初始化 而且不能被更新 常对象 必须进行初始化 不能被更新 const类名对象名或 类名const对象名常引用 被引用的对象不能被更新 const类型说明符 引用名常数组 数组元素不能被更新 后面讲 类型说明符const数组名 大小 常指针 指向常量的指针 后面讲 5 共享数据的保护 常对象用const修饰的类成员常引用 常对象 常对象的数据成员值在对象的整个生存期间不能被改变 即 常对象必须进行初始化 而且不能被更新 声明常对象的语法形式 const类型说明符对象名 或 类型说明符const对象名 与基本数据类型的常量相似 常对象的值也是不能被改变的 常对象举例 classA public A inti intj x i y j private intx y constAa 3 4 a是常对象 不能被更新 常对象 C 语法如何保障类型的常对象的值 常对象的数据成员 不被改变呢 改变对象的数据成员值可以通过类的成员函数进行 因此 语法规定不能通过常对象来调用普通的成员函数 可是如此一来 常对象还有什么用呢 因为这样的话 常对象就没有任何可用的对外接口了 常成员函数可以解决这个问题 用const修饰的类成员 常成员函数使用const关键字说明的函数 常成员函数不更新对象的数据成员 常成员函数说明格式 类型说明符函数名 参数表 const 这里 const是函数类型的一个组成部分 因此在实现部分也要带const关键字 const关键字可以被用于参与对重载函数的区分通过常对象只能调用它的常成员函数 常数据成员使用const说明的数据成员 例5 7常成员函数举例 includeusingnamespacestd classR public R intr1 intr2 R1 r1 R2 r2 voidprint voidprint const private intR1 R2 voidR print cout R1 R2 endl voidR print const cout R1 R2 endl intmain Ra 5 4 a print 调用voidprint constRb 20 52 b print 调用voidprint constreturn0 运行结果 5 420 52 例5 7 函数重载的3种情况 C 允许功能相近的函数在相同的作用域内以相同的函数名定义 从而形成函数重载 函数重载必须在满足下列3种情况之一时才能成立 例5 8常数据成员举例 includeusingnamespacestd classA public A inti voidprint private constinta 常数据成员staticconstintb 静态常数据成员 constintA b 10 静态常数据成员在类外说明和初始化A A inti a i a i 常数据成员只能通过初始化列表来获得初值voidA print cout a b endl intmain 建立对象a1和a2 并以100和0作为初值 分别调用构造函数 通过构造函数的初始化列表给对象的常数据成员赋初值Aa1 100 a2 0 a1 print a2 print return0 运行结果 100 100 10 例5 8 常引用 如果在声明引用时用const修饰 被声明的引用就是常引用 常引用所引用的对象不能被更新 如果用常引用作形参 就不会意外地发生对实参的更改 常引用的声明形式如下 const类型说明符 例5 9常引用作形参 include includeusingnamespacestd classPoint Point类定义public 外部接口Point intxx 0 intyy 0 x xx y yy intgetX returnx intgetY returny friendfloatdist constPoint floatdist constPoint 例5 9 运行结果 Thedistanceis 5 第5章数据的共享与保护 1 标识符的作用域与可见性2 对象的生存期3 类的静态成员 微视频 4 类的友元5 共享数据的保护 微视频 6 多文件结构和编译预处理命令 微视频 7 综合实例 个人银行账户管理程序 微视频 8 小结 6 多文件结构和编译预处理命令 C 程序的一般组织结构外部变量与外部函数标准C 库编译预处理 C 程序的一般组织结构 一个源程序可以划分为多个源文件 类声明文件 h文件 类实现文件 cpp文件 类的使用文件 main 所在的 cpp文件 利用工程 project 来组合各个文件 例5 10文件1 类的声明 point h 文件1 类的声明 point h ifndefPOINT H definePOINT HclassPoint 类的定义public 外部接口Point intxx 0 intyy 0 x xx y yy count Point constPoint endif 例5 10文件2 类的实现 Point cpp 文件2 类的实现 Point cpp include Point h includeusingnamespacestd intPoint count 0 使用类名初始化静态数据成员Point Point constPoint 例5 10文件3 主函数 5 10 cpp include Point h includeusingnamespacestd intmain Pointa 4 5 定义对象a 其构造函数会使count增1cout PointA a getX a getY Point showCount 输出对象个数Pointb a 定义对象b 其构造函数会使count增1cout PointB b getX b getY Point showCount 输出对象个数return0 运行结果 PointA 4 5Objectcount 1PointB 4 5Objectcount 2 外部变量与外部函数 为了使变量除了在定义它的源文件中可以使用外 还要被其他文件使用 可以将其声明为外部变量 用extern关键字来说明 如果在声明一个函数原型时或定义函数时冠以static关键字来修饰 就将函数的作用域限制在了当前的编译单元内 这时编译器要求当前编译单元内必须包含函数的定义 而且此函数定义只在当前编译单元内可见 这样在其他的编译单元中 就不能调用这个函数 外部变量 cpp includeusingnamespacestd inti 3 全局变量 文件作用域voidnext void intmain i next cout i i endl 输出5return0 voidnext i 运行结果 i 5 文件名 外部变量1 cpp includeusingnamespacestd inti 3 全局变量 文件作用域voidnext intmain i next cout i i endl return0 文件名 外部变量2 cppexterninti staticvoidnext void voidnext void 外部函数i 运行结果 i 5 外部变量 cpp 若 外部变量2 cpp 写成如下形式 externinti staticvoidnext void voidnext void 外部函数i 则该文件的编译可以通过 但是在连接时出错 标准C 库 标准C 类与组件在逻辑上分为6种类型 输入输出类 容器类与ADT 抽象数据模型 存储管理类 算法 错误处理 运行环境支持 对库中预定义内容的声明分别存在于不同的头文件中 要使用这些预定义的成分 就要将相应的头文件包含到源程序中 使用 include预处理指令 标准C 库 使用标准C 库时 还需要加入下面这一条语句来将指定命名空间中的名称引入到当前作用域中 usingnamespacestd 如果不使用上述方法 就需要在使用std命名空间中任何标识符时 都冠以命名空间名 std 通常情况下 usingnamespacestd 语句不宜放在头文件中 因为这会使一个命名空间不被察觉地对一个源文件开放 编译预处理 在编译器对源程序进行编译之前 首先要由预处理器对程序文本进行预处理 预处理器提供了一组编译预处理指令和预处理操作符 预处理指令实际上不是C 语言的一部分 它只是用来扩充C 程序设计的环境 所有的预处理指令在程序中都是以 来引导 每一条预处理指令单独占用一行 不要用分号结束 预处理指令可以根据需要出现在程序中的任何位置 编译预处理 include指令 define和 undef指令条件编译指令defined操作符 include指令 include指令也称文件包含指令 其作用是将另一个源文件嵌入到当前源文件中该点处 文件包含指令有如下2种格式 include按标准方式搜索 文件位于系统目录的include子目录下 include 文件名 首先在当前目录中搜索 若没有找到 再按标准方式搜索 define和 undef指令 define也称宏定义指令 其最初是为C语言设计的 但是 define能完成的一些功能 能够被C 引入的一些语言特性很好地替代 不带参数的宏定义 definePI3 14 constdoublePI 3 14 带参数的宏定义 defineMU X Y X Y 内联函数 define和 undef指令 用 define定义空符号 defineMYHEAD H将该符号配合条件编译指令一起使用 可以起到一些特殊作用 undef的作用是删除由 define定义的宏 条件编译指令 使用条件编译指令 可以限定程序中的某些内容要在满足一定条件的情况下才参与编译 因此 利用条件编译可以使同一个源程序在不同的编译条件下产生不同的目标代码 例如 可以在调试程序时增加一些调试语句 以达到跟踪的目的 并利用条件编译指令 限定当程序调试好后 重新编译时 使调试语句不参与编译 条件编译指令 常用的条件编译语句有下列5种形式 形式一 if常量表达式程序段 当 常量表达式 非零时编译本程序段 endif 形式二 if常量表达式程序段1 当 常量表达式 非零时编译本程序段 else程序段2 当 常量表达式 为零时编译本程序段 endif 条件编译指令 形式三 if常量表达式1程序段1 当 常量表达式 非零时编译本程序段 elif常量表达式2程序段2 当 常量表达式1 为零 常量表达式2 非零时编译本程序段 elif常量表达式n程序段n 当 常量表达式1 常量表达式n 1 均为零且 常量表达式n 非零时编译本程序段 else程序段n 1 其他情况下编译本程序段 endif 条件编译指令 形式四 ifdef标识符程序段1 else程序段2 endif如果 标识符 经 define定义过 且未经 undef删除 则编译程序段1 否则编译程序段2 如果没有程序段2 则 else可以省略 ifdef标识符程序段1 endif 条件编译指令 形式五 ifndef标识符程序段1 else程序段2 endif如果 标识符 未经 define定义过 且未经 undef删除 则编译程序段1 否则编译程序段2 如果没有程序段2 则 else可以省略 ifndef标识符程序段1 endif defined操作符 defined是一个预处理操作符 而不是指令 因此不要以 开头 defined操作符使用形式为 defined 标识符 若 标识符 在此前经 define定义过 并且未经 undef删除 则上述表达式为非0 否则上述表达式为0 下面两种写法完全等效 不使用条件编译的头文件 由于文件包含指令可以嵌套使用 在设计程序时要避免多次重复包含同一个头文件 否则会引起变量及类的重复定义 main cpp include file1 h include file2 h intmain file1 h include head h file2 h include head h head h classPoint 使用条件编译的头文件 head h ifndefHEAD H defineHEAD H classPoint endif 在前面的例子中 由于 include指令的嵌套使用 使得头文件head h被包含两次 因此编译时系统会指出错误 类Point被重复定义 为了避免这种情况 就要在可能被重复包含的头文件中使用条件编译指令 用一个唯一的标识符来标记某文件是否已参加过编译 如果已参加过编译 则说明该程序段是被重复包含的 编译时将忽略重复部分 将文件 head h 改写如右侧所示 第5章数据的共享与保护 1 标识符的作用域与可见性2 对象的生存期3 类的静态成员 微视频 4 类的友元5 共享数据的保护 微视频 6 多文件结构和编译预处理命令 微视频 7 综合实例 个人银行账户管理程序 微视频 8 小结 7 综合实例 个人银行账户管理程序 对上一章综合实例的程序做如下改进 为SavingsAccount类增加一个静态数据成员total 用来记录各个账户的总金额 并为其增加相应的静态成员函数getTotal 用来对其进行访问 将SavingsAccount类中诸如getBalance accumulate这些不需要改变对象状态的成员函数声明为常成员函数 7 综合实例 个人银行账户管理程序 将SavingsAccount类从主函数所在的源文件中分开 建立两个新的文件account h和account cpp 分别存放SavingsAccount类的定义和实现 总之 本例的类设计与上一章综合实例大致相同 只是做了一些不大的改动 在类S
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- XX建筑工程有限公司合约采购部内勤岗位职责
- 缓解压力奔赴高考荣光
- 医院消防安全标准化建设
- 颅内占位知识普及
- 腰椎病健康宣教与预防
- 决战AI:技术与应用
- 腹透患者护理
- 健康调查问卷模板
- AI在光伏工程技术中的应用
- AI在饲草生产技术中的应用
- 驾驶员交通安全知识讲座讲话稿范文
- 慢性肾脏病矿物质及骨代谢异常
- MOOC 跨文化交际通识通论-扬州大学 中国大学慕课答案
- (正式版)SHT 3078-2024 立式圆筒形料仓工程设计规范
- JC∕T 60016-2022 建筑用免拆复合保温模板应用技术规程
- 中医四诊在骨科评估中应用护理课件
- 沈阳恒昌塑料制品厂建设项目环境影响报告
- 无人机飞行原理-第08章 无人直升机飞行性能
- 著作权法法律保护
- 颈椎病中医治疗及康复
- GB/T 17465.6-2022家用和类似用途器具耦合器第3部分:标准活页和量规
评论
0/150
提交评论