面向对象程序设计-7_第1页
面向对象程序设计-7_第2页
面向对象程序设计-7_第3页
面向对象程序设计-7_第4页
面向对象程序设计-7_第5页
已阅读5页,还剩35页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、第第7 7讲讲 C+C+程序结构程序结构2本讲主要内容本讲主要内容友元编译预处理命令多文件结构和工程深度探索指针与引用 3友元友元友元是C+提供的一种破坏数据封装和数据隐藏的机制。通过将一个模块声明为另一个模块的友元,一个模块能够引用到另一个模块中本是被隐藏的信息。为了确保数据的完整性,及数据封装与隐藏的原则,建议尽量不使用或少使用友元。 友 元4友元函数友元函数友元函数是在类声明中由关键字friend修饰说明的非成员函数,在它的函数体中能够通过对象名访问 private 和 protected成员作用:增加灵活性,使程序员可以在封装和快速性方面做合理选择。访问对象中的成员必须通过对象名。 友

2、 元5例例5-6 5-6 使用友元函数计算两点距离使用友元函数计算两点距离#include #include class Point /Point类声明public:/外部接口Point(int x=0, int y=0) : x(x), y(y) int getX() return x; int getY() return y; friend float dist(Point &a, Point &b); private:/私有数据成员int x, y; 友 元float dist( Point& a, Point& b) double x = a.x - b

3、.x; double y = a.y - b.y; return static_cast(sqrt(x * x + y * y);int main() Point p1(1, 1), p2(4, 5); cout The distance is: ; cout dist(p1, p2) endl; return 0;367友元类友元类若一个类为另一个类的友元,则此类的所有成员都能访问对方类的私有成员。声明语法:将友元类名在另一个类中使用friend修饰说明。 友 元8友元类举例友元类举例class A friend class B;public: void display() cout x e

4、ndl; private: int x;class B public: void set(int i); void display();private: A a; 友 元void B:set(int i) a.x=i;void B:display() a.display();3910友元关系是单向的友元关系是单向的如果声明B类是A类的友元,B类的成员函数就可以访问A类的私有和保护数据,但A类的成员函数却不能访问B类的私有、保护数据。11常类型常类型 常类型的对象必须进行初始化,而且不能被更新。常对象:必须进行初始化,不能被更新。const const 类名类名 对象名对象名常引用:被引用的对象

5、不能被更新。const const 类型说明符类型说明符 & &引用名引用名常数组:数组元素不能被更新。类型说明符类型说明符 const const 数组名数组名 大小大小.常指针:不能通过指针改变对象值,指针本身可以改变。 共享数据的保护12常对象举例常对象举例class A public: A(int i,int j) x=i; y=j; . private: int x,y;A const a(3,4); /a是常对象,不能被更新 共享数据的保护13用用constconst修饰的对象成员修饰的对象成员常成员函数使用const关键字说明的函数。常成员函数不更新对象的数据成员

6、。常成员函数说明格式:类型说明符 函数名(参数表)const;这里,const是函数类型的一个组成部分,因此在实现部分也要带const关键字。const关键字可以被用于参与对重载函数重载函数的区分通过常对象只能调用它的常成员函数常对象只能调用它的常成员函数。常数据成员使用const说明的数据成员。 共享数据的保护14例例5-7 5-7 常成员函数举例常成员函数举例#includeusing namespace std;class R public: R(int r1, int r2) : r1(r1), r2(r2) void print(); void print() const;priva

7、te: int r1, r2; 共享数据的保护void R:print() cout r1 : r2 endl;void R:print() const cout r1 ; r2 endl;int main() R a(5,4); a.print(); /调用void print() const R b(20,52); b.print(); /调用调用void print() constreturn 0;4516例例5-8 5-8 常数据成员举例常数据成员举例#include using namespace std;class A public:A(int i);void print();pr

8、ivate:const int a;static const int b; /静态常数据成员; 共享数据的保护const const intint A:b=10; A:b=10; A:A(int i) : a(a(i i) ) void A:print() cout a : b endl;int main() /*建立对象a和b,并以100和0作为初值,分别调用构造函数,通过构造函数的初始化列表给对象的常数据成员赋初值通过构造函数的初始化列表给对象的常数据成员赋初值*/ A a1(100), a2(0); a1.print(); a2.print(); return 0;475.5.3 5.5

9、.3 常引用常引用声明引用时用const修饰,则为常引用 const const 类型说明符类型说明符 & & 引用名引用名常引用所引用的对象不能被更新作用:当用常引用作为形参,便不会意外地发生对实参的修改19例例5-95-9常引用作形参常引用作形参#include #include using namespace std;class Point /Point类定义public:/外部接口Point(int x = 0, int y = 0) : x(x), y(y) int getX() return x; int getY() return y; friend float

10、dist(const Point &p1, const Point dist(const Point &p1, const Point &p2&p2);private:/私有数据成员int x, y; 共享数据的保护例例5-95-9常引用作形参常引用作形参float dist(float dist(const Point &p1, const Point &p2const Point &p1, const Point &p2) ) double x = p1.x - p2.x;double x = p1.x - p2.x;doub

11、le y = p1.y - p2.y;double y = p1.y - p2.y;return return static_caststatic_cast(sqrtsqrt(x (x * * x + y x + y * * y); y); intint main() main() /主函数主函数const Point myp1(1, 1), myp2(4, 5);const Point myp1(1, 1), myp2(4, 5);coutcout The distance is: ; The distance is: ;coutcout dist(myp1, myp2) dist(myp1

12、, myp2) endlendl; ;return 0;return 0; 20 共享数据的保护21编译预处理命令编译预处理命令#include 包含指令将一个源文件嵌入到当前源文件中该点处。#include 按标准方式搜索,文件位于C+系统目录的include子目录下#include文件名 首先在当前目录中搜索,若没有,再按标准方式搜索。#define 宏定义指令定义符号常量,很多情况下已被很多情况下已被constconst定义语句取代定义语句取代。(思考:const的优势?)定义带参数宏,已被内联函数取代。#undef删除由#define定义的宏,使之不再起作用。22条件编译指令条件编译指

13、令 #if #if 和和 #endif#endif#if 常量表达式 /当“ 常量表达式”非零时编译 程序正文 #endif. 编译预处理命令23条件编译指令条件编译指令#else#else #if 常量表达式 /当“ 常量表达式”非零时编译 程序正文1#else /当“ 常量表达式”为零时编译 程序正文2#endif 编译预处理命令24条件编译指令条件编译指令 #elif#elif#if 常量表达式1 程序正文1 /当“ 常量表达式1”非零时编译#elif 常量表达式2 程序正文2 /当“ 常量表达式2”非零时编译#else 程序正文3 /其他情况下编译#endif 编译预处理命令25条件编

14、译指令条件编译指令#ifdef 标识符 程序段1#else 程序段2#endif如果“标识符”经#defined定义过,且未经undef删除,则编译程序段1,否则编译程序段2。 编译预处理命令26条件编译指令条件编译指令#ifndef 标识符 程序段1#else 程序段2#endif如果“标识符”未被定义过,则编译程序段1,否则编译程序段2。 编译预处理命令27多文件结构(例多文件结构(例5-10 p1685-10 p168)一个源程序可以划分为多个源文件:类声明文件(.h文件)类实现文件(.cpp文件)类的使用文件(main()所在的.cpp文件)利用工程来组合各个文件。28不使用条件编译的

15、头文件不使用条件编译的头文件/main.cpp#include file1.h#include file2.hint main() /file1.h#include head.h /file2.h#include head.h /head.h class Point 多文件结构29使用条件编译的头文件使用条件编译的头文件/head.h#ifndef HEAD_H #define HEAD_H class Point #endif 多文件结构代码的编译代码的编译编译:源文件目标文件源文件的函数代码目标文件的代码段源文件的静态对象目标文件的数据段 分为初始化的数据段和未初始化的数据段符号表:将静态

16、对象与函数的名字与地址关联重定位信息、其它信息30深 度 探 索示例代码示例代码(1)(1)a.cppextern int y;int func(int v);int main() int z = 1;y = func(z);return 0;31(main的代码)lea 0 x4(%esp),%ecxand $0 xfffffff0,%esp代码段(.text)a.o未定义_Z4funci未定义ymain符号表深 度 探 索示例代码示例代码(2)(2)32(func的代码)push %ebpmov %esp,%ebp代码段(.text)(x的初值) 3初始化的数据段(.data)(y)未初始

17、化的数据段(.bss)xy_Z4funci符号表b.ob.cppint x = 3;int y;int func(int v) return v + x;深 度 探 索代码的连接与执行代码的连接与执行连接将各段合并将符号表综合根据重定位信息,确定代码中用到的全局地址代码的执行操作系统首先将文件从磁盘读入,初始化各段一些静态数据就在此时被初始化从引导代码开始执行,引导代码启动main,main返回后,引导代码通知操作系统程序结束33深 度 探 索指针与引用的对应关系指针与引用的对应关系/使用指针常量void swap(int * const pa, int * const pb) int tem

18、p = *pa;*pa = *pb;*pb = temp;int main() int a, b;swap(&a, &b);return 0;/使用引用void swap(int &ra, int &rb) int temp = ra;ra = rb;rb = temp;int main() int a, b;swap(a, b);return 0;34 深度探索指针与引用的联系指针与引用的联系引用在底层通过指针来实现一个引用变量,通过存储被引用对象的地址,来标识它所引用的对象引用是对指针的包装,比指针更高级指针是C语言就有的底层概念,使用起来很灵活,但用不好容

19、易出错引用隐藏了指针的“地址”概念,不能直接对地址操作,比指针更安全35 深度探索引用与指针的选择(引用与指针的选择(区别见区别见p242p242)什么时候用引用?如无需直接对地址进行操作,指针一般都可用引用代替用更多的引用代替指针,更简洁、安全什么时候用指针?引用的功能没有指针强大,有时不得不用指针: 引用一经初始化,无法更改被引用对象,如有这种需求引用一经初始化,无法更改被引用对象,如有这种需求,必须用指针;,必须用指针; 没有空引用,但有空指针,如果空指针有存在的必要,没有空引用,但有空指针,如果空指针有存在的必要,必须用指针;必须用指针; 函数指针;函数指针; 用用newnew动态创建

20、的对象或数组,用指针存储其地址最自然动态创建的对象或数组,用指针存储其地址最自然; 函数调用时,以数组形式传递大量数据时,需要用指针函数调用时,以数组形式传递大量数据时,需要用指针作为参数。作为参数。36 深度探索指针的地址安全性问题指针的地址安全性问题地址安全性问题通过指针,访问了不该访问的地址,就会出问题典型问题:数组下标越界问题的严重性:有时会在不知不觉中产生错误,错误源很难定位,因此程序调试起来很麻烦解决方案指针只有赋了初值才能使用(这一点普通变量也应遵循)指针的算术运算,一定要限制在通过指向数组中某个元素的指针,得到指向同一个数组中另一个元素的指针尽量使用封装的数组(如vector),而不直接对指针进行操作

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论