已阅读5页,还剩3页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
友元 类的主要特点之一是数据隐藏,即类的私有成员只能在类定义的范围内使用,也就是 说私有成员只能通过它的成员函数来访问。但是,有时候需要在类的外部访问类的私有成 员。为此,就需要寻找一种途径,在不放弃私有数据安全性的情况下,使得类外部的函数或 类能够访问类中的私有成员,在C+中就用友元作为实现这个要求的辅助手段。C+中的友元为数据隐藏这堵不透明的墙开了一个小孔,外界可以通过这个小孔窥视类内部的秘密,友元是一扇通向私有成员的后门。 友元既可以是不属于任何类的一般函数,也可以是另一个类的成员函数,还可以是整 个的一个类(这样,这个类中的所有成员函数都可以成为友元函数)。3.6.1 友元函数 友元函数不是当前类的成员函数,而是独立于当前类的外部函数,但它可以访问该类 的所有对象的成员,包括私有成员和公有成员。 在类定义中声明友元函数时,需在其函数名前加上关键字friend。此声明可以放在公有部分,也可以放在私有部分。友元函数可以定义在类内部,也可以定义在类的外部。 下面是一个使用友元函数的例子。例3.1#include#includeclass girl char *name; int age;public: girl(char *n,int d) name=new charstrlen(n)+1; strcpy(name,n); age=d; friend void disp(girl &); /声明友元函数 girl() delete name; ; void disp(girl &x) /定义友元函数 coutgirls name is: , age: x.agen; void main() girl e(Chen Xingwei, 18); disp(e); /调用友元函数程序的运行结果如下: girls name is:Chen Xingwei,age:18 从上面的例子可以看出,友元函数可以访问类对象的各个私有数据。若在类girl的声 明中将友元函数的声明语句去掉,那么函数disp()对类对象的私有数据的访问将变为非法的。说明:(1)友元函数虽然可以访问类对象的私有成员,但它毕竟不是成员函数。因此,在类的外部定义友元函数时,不必像成员函数那样,在函数名前加上“类名:”。(2)友元函数一般带有一个该类的入口参数。因为友元函数不是类的成员,所以它不能直接引用对象成员的名字,也不能通过this指针引用对象的成员,它必须通过作为入口参数传递进来的对象名或对象指针来引用该对象的成员。 例如上面例子中的友元函数void disp(girl &x)就带有该类的一个入口参数。(3)当一个函数需要访问多个类时,友元函数非常有用,普通的成员函数只能访问其所属的类,但是多个类的友元函数能够访问相应的所有类的数据。 例如有boy和girl两个类,现要求打印出所有的男生和女生的名字和年龄,我们只需 一个独立的函数prdata()就能够完成,但它必须同时定义为这两个类的友元函数。下例 给出了这样的一个程序。例3.2#include#includeclass boy; /向前引用class girl char name25; int age;public: void init(char N,int A); friend void prdata(const girl plg,const boy plb); /声明prdata()为girl的友元函数;void girl:init(char N,int A) strcpy (name ,N); age=A;class boy char name25; int age;public: void init(char N,int A); friend void prdata(const girl plg,const boy plb); /声明prdata()为boy的友元函数;void boy:init(char N,int A) strcpy(name,N); age=A;void prdata(const girl plg,const boy plb) /定义友元函数prdata() coutname: n; coutage: plg.agen; coutname: n; coutage: plb.agen;void main ( ) girl G1,G2,G3; boy B1,B2,B3; G1.init(Stacy, 12); G2.init(Judith, 13); G3.init(Leah ,12); B1.init(Jim,11); B2.init(Michael, 13); B3.init ( Larry, 12); prdata(G1, B1); /调用友元函数prdata() prdata(G2, B2); /调用友元函数prdata() prdata(G3, B3); /调用友元函数prdata()程序运行结果如下; name:Stacy age:12 name:Jim age:11 name:Judith age:13 name:Michael age:13 name:Leah age:12 name:Larry age:12程序中的第3行是由于第9行的要求而存在的。因为友元函数带了两个不同的类的 对象,其中一个是类boy的对象,而类boy要在晚一些时候才被声明。为了避免编译时的 错误,编程时必须通过向前引用(forward reference)告诉C+类boy将在后面定义。在向前引用类声明之前,可以使用该类声明参数,这样第9行就不会出错了。 prdata()是程序中的一个独立函数,可以被main()或其它任意函数调用。但由于它被 定义成类boy和类girl的友元函数,所以它能够访问这两个类中的私有数据。友元函数通过直接访问对象的私有成员,提高了程序运行的效率。在某些情况下,如运算符被重载时,需要用到友元。但是友元函数破坏了数据的隐蔽性,降低了程序的可维护性,这与面向对象的程序设计思想是背道而驰的,因此使用友元函数应谨慎。3.6.2 友元成员 除了一般的函数可以作为某个类的友元外,一个类的成员函数也可以作为另一个类 的友元,这种成员函数不仅可以访问自己所在类对象中的私有成员和公有成员,还可以访 问friend声明语句所在类对象中的私有成员和公有成员,这样能使两个类相互合作、协调 工作,完成某一任务。 在例3.3所列的程序中,声明了disp()为类boy的成员函数,又是类girl的友元函数。例3.3#include#includeclass girl;class boy char * name; int age;public: boy(char *n,int d) name=new charstrlen(n)+1; strcpy (name,n); age=d; void disp(girl &); /声明disp()为boy的成员函数 boy() delete name; ;class girl char *name; int age;public: girl(char *n,int d) name=new charstrlen(n)+1; strcpy(name,n); age=d; friend void boy:disp(girl &); /声明boy的成员函数disp()为girl的友元函数 girl() delete name; ;void boy:disp(girl &x) /定义友元函数disp() cout boys name is: name, age: agen; cout girls name is: , age: x.agen;void main() boy b(chen hao ,25); girl e(zhang wei,18); b.disp (e);程序运行结果如下: boys name is:chen hao,age:25 girls name is:zhang wei,age:18说明:(1)一个类的成员函数作为另一个类的友元函数时,必须先定义这个类。例如上例中,类boy的成员函数为类girl的友元函数,必须先定义类boy。并且在声明友元函数时,要加上成员函数所在类的类名,如: friend void boy:disp(girl&);(2)程序中第3行class girl;”为向前引用,因为函数disp()中将girl&作为参数,而girl在要晚一些时候才被定义。3.6.3 友元类 不仅函数可以作为一个类的友元,一个类也可以作为另一个类的友元。这种友元类的 说明方法是在另一个类声明中加入语句“friend 类名(即友元类的类名),”,此语句可以 放在公有部分也可以放在私有部分,例如: class Y/. ; class X /. friendY; /声明类Y为类X的友元类/ ; 当一个类被说明为另一个类的友元时,它的所有的成员函数都成为另一个类的友元 函数,这就意味着作为友元的类中的所有成员函数都可以访问另一个类中的私有成员。 下面的例子中,声明了两个类boy和girl,类boy声明为类girl的友元,因此类boy的成员函数都成为类girl的友元函数,它们都可以访问类girl的私有成员。例3.25#include#includeclass girl;class boy char *name; int age;public: boy(char *n,int d) name=new charstrlen(n)+1; strcpy (name,n); age=d; void disp(girl &); /声明disp()为类boy的成员函数 boy() delete name;class girl char * name; int age; friend boy; /声明类boy是类girl的友元public: girl(char *n,int d) name=new charstrlen(n)+1; strcpy (name,n); age=d; girl () delete name;void boy:disp(girl &x) /定义函数disp()为类boy的成员函数, /也是类girl的友元函数 cout boys name is: name, age: agen; cout girls name is: , age: x.agen;void main () boy b(chen hao,25); girl e(zhang wei,18); b.disp(e);程序运行结果如下: boys name is:chen hao,age:25 girls name is:zhang wei,age:18 说明:友元关系是单向的,不具有交换性。若类X是类Y的友元(即在类Y定义中声明X为friend类),类Y是否是X的友元,要看在类中是否有相应的声明。友元关系也不具有传递性,若类X是类Y的友元,类Y是类Z的友元,不一定类X是类Z的友元。3.7 类对象作为成员 在类定义中定义的数据成员一般都是基本的数据类型。但是类中的成员也可以是对 象,叫做对象成员。使用对象成员着重要注意的问题是构造函数的定义方式,即类内部对象的初始化问题。含有对象成员的类,其构造函数和不含对象成员的构造函数有所不同,例如有以下的类: class X 类名1 成员名1: 类名2 成员名2; 类名n 成员名n; ; 一般来说,类X的构造函数的定义形式为:X:X(参数表0):成员名1(参数表1),成员名n(参数表n) 构造函数体 冒号后面的部分是对象成员的初始化列表,各对象成员的初始化列表用逗号分隔,参数表i(i为1到n)给出了初始化对象成员所需要的数据,它们一般来自参数表。 当调用构造函数X:X()时,首先按各对象成员在类定义中的顺序依次调用它们的构造函数,对这些对象初始化,最后再执行X:X()的函数体。析构函数的调用顺序与此相反。 下面的例子中有两个类string和girl,类girl中的一个数据成员name是类string的一个对象,即name是类girl的一个对象成员。两个类都有各自的构造函数,而类girl的构造函数被执行时,希望能给其中的string类的成员对象也初始化为具体的值。例3.26#include#includeclass string /声明类string private: char *str; public: string(char *s) /定义类string的构造函数 str=new charstrlen(s)+1; strcpy(str, s); void print () coutstrendl; string() delete str; ;class girl /声明类girl private: string name; /name为类girl的对象成员 int age; public: girl(char *st, int ag):name(st) /定义类girl的构造函数 age=ag; void print () name.print(); /调用类string的对象name的成员函数print() coutage:ageendl; girl() ;void main() girl obj(Chen hao,25); obj.print();程序运行结果如下: chen hao age:25说明:(1)声明一个含有对象成员的类,首先要创建各成员对象。本例在声明类girl中,定义了对象成员name: s
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 冷冻肉购销合同范本
- 山东微山县事业单位2025年下半年招考人才易考易错模拟试题(共500题)试卷后附参考答案
- 宜昌市人力资源和社会保障局所属事业单位2025年下半年急需紧缺人才引进【2人】易考易错模拟试题(共500题)试卷后附参考答案
- 供电合同解除协议书
- 公司宽带安装协议书
- 出售储能电合同范本
- 桂圆买卖合同协议书
- 框架协议框架协议书
- 桌椅板凳租赁协议书
- 元件备货协议书范本
- 联合派遣合同协议
- 结伴自驾协议书范本
- 具身智能机器人在养老服务中的价值与伦理考量
- 城市安全风险综合监测预警平台建设实施方案
- 【MOOC】思辨式英文写作-南开大学 中国大学慕课MOOC答案
- 银行征信管理专项审计的报告
- 妇科手术快速康复总结
- 数据治理咨询项目技术方案
- 警校生未来职业规划
- 胃癌多学科综合治疗方案优化
- 营养强化盐,你了解多少-
评论
0/150
提交评论